C# 3.0 版和 Visual Studio 2008 一起发布于 2007 年下半年,但完整的语言功能是在 .NET Framework 3.5 版中发布的。 此版本标示着 C# 发展过程中的重大更改。 C# 成为了真正强大的编程语言。

一、隐式类型var

从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var。隐式类型可以替代任何类型,编译器自动推断类型。

1、var类型的局部变量必须赋予初始值,包括匿名类(初始值不能为null)。

var s = ”c#”;
var name = new {name=”aa”,age=24};

2、隐式类型的数组

var a = new[]{100};//int[] a=new int[]{1,10,100}
var b = new[]{new[]{1,2,3},new[] {4,5,6}}//交错数组也可用new[]初始化,不支持隐式类型的多位数组。

3、var 只能作为局部变量使用,即只能定义在方法内或在属性get、set访问器中。还可用于foreach ,for , using语句中。

public string Name
{
get
{
var p = new Person();//正确
return p.Name;
}
}
for(var i=0;i<10,i++)
{} using (var file=new StreamReader(“”)
{}

4、var 多数情况在匿名类型和LINQ中使用。

    string[] words = { "aa", "bb", "cc" };
var upperLower = from w in words
select new { Upper = w.ToUpper(), Lower = w.ToLower() };
foreach (var word in upperLower)
{
Console.WriteLine(word.Upper+","+ word.Lower);
}

二、扩展方法

使您能够向现有类型“添加”方法,而无需创建新的派生类型。

1、最常见的扩展方法是LINQ标准查询运算符。

扩展方法向IEnumerable和IEnumerable类型添加查询功能。

int[] ints={10,45,15,39};
var result=ints.OrderBy(g=>g);//扩展方法是一种特殊的静态方法,但可像扩展类型上的实例方法一样进行调用。
foreach(var i in result)
{
Console.Write(i);
}

2、对已有的类型进行扩展。

所有的扩展方法写在一个静态类中,相当于存放扩展方法的容器。

所有的扩展方法为静态方法。

扩展方法的第一个参数this后跟着的类表示要扩展的类型。扩展方法第一个参数后才是真正的参数列表。

void Main()
{
string s = "Hello Extension";
int i = s.WordCount();
Console.WriteLine(i.ToString());
} public static class MyExtensions //所有的扩展方法写在一个静态类中,相当于存放扩展方法的容器。
{
public static int WordCount(this String str)//this String表示要扩展的类型。扩展方法第一个参数后才是真正的参数列表
{
return str.Split(new char[] { ' ', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
}

三、自动实现的属性

当属性访问器中不需要其他逻辑时,自动实现的属性声明更为简洁。

1、自动实现的属性必须同时声明get和set访问器。

public int One{get;set;}

2、使用private set设置只读的自动属性,在定义此属性的类本身中还是可以初始化赋值的。

public string Name{get;private set;}

3、自动实现的属性不允许具有Attribute属性。

四、对象/集合初始值设定项

1、对象初始值设定项

可以在创建对象时向对象的可访问字段或属性赋值,而无需显示调用构造函数。从 C# 6 开始,除了分配字段和属性外,对象初始值设定项还可以设置索引器。

例1:简单应用

public class Cat
{
public string name { set; get; }
public int age { get; set; }
} void Main()
{
//老式
Cat x = new Cat();
x.name = "aa";
x.age = 1; //对象初始值设定项
Cat x1 = new Cat
{
name = "aa",
age = 1
};
Console.Write(x1.age);
}

例2:嵌套应用

class Rectangle
{
public Point P1 { set; get; }
public Point P2 { set; get; } public Rectangle()
{
P1 = new Point();
P2 = new Point();
}
}

void Main()
{
Rectangle myRec = new Rectangle
{
P1 = new Point() { X = 1, Y = 1 },
P2 = new Point() { X = 200, Y = 200 }
};
Console.Write(myRec.P2.Y);
}

2、集合初始值设定项

无需再代码中指定对该集合类的多个Add方法调用,编译器自动添加调用。

集合类必须实现IEumerable。

例1:

List<int> list=new List<int> {0,1,2,3};

例2:

List a = new List
{
new Rectangle {P1 = { X = 1, y = 1 },P2 = { X = 200, y = 200 },
new Rectangle {P1 = { X = 1, y = 1 },P2 = { X = 200, y = 200 }
} //如果Add方法允许,可以将null指定为其中的一个元素

例3、如果集合支持读取/写入索引,可以指定索引元素。

var numbers = new Dictionary<int, string>
{
[7] = "seven",
[9] = "nine",
[13] = "thirteen"
};

注意:前面的示例生成调用 Item[TKey] 以设置值的代码。 从 C# 6 开始,可以使用以下语法初始化字典和其他关联容器。  它使用具有多个值的对象,此初始值设定项示例调用 Add(TKey, TValue),将这三个项添加到字典中。

var moreNumbers = new Dictionary<int, string>
{
{19, "nineteen" },
{23, "twenty-three" },
{42, "forty-two" }
};

由于编译器生成的方法调用不同,这两种初始化关联集合的不同方法的行为略有不同。 这两种变量都适用于 Dictionary 类。 其他类型根据它们的公共 API 可能只支持两者中的一种。

五、匿名类型

匿名类型是编译器动态创建的一个类,用于存储一组值。

要创建匿名类型,请使用new关键字和对象初始化器,指定类型将包含的属性和值。

可以将一组只读属性封装到单个对象中,无需首先定义一个类型。匿名类型只能用于定义它的方法中。

匿名类型由一个或多个公共只读属性组成。成员不能用null赋初值。如果多个匿名类型有相同数量和种类的属性,编译器将视为相同的类型,生成多个实例。

var noName = new { name = "a", 
                   age = 1 };
Console.Write(noName.name);

1、匿名类型的属性名称可以从表达式中推断出来:

int Age = 3;
var person = new { Name = "Jack", Age, Age.ToString().Length };

相当于:

var person = new { Name = "Jack", Age = Age, Length = Age.ToString().Length };

2、由匿名类型构成的数组

var anonArray = new[] { new { name = "apple", diam = 4 }, 
                        new { name = "grape", diam = 1 }};

生成匿名类型数组

var result = new
{
pages = 10,
Users = from mo in list
select new
{
id = mo.UserId,
name = mo.Nick
}
};

可以生成:

var result = new
{
pages = 10,
users = new[]{
new{id=1,name="2"}
new{id=2,name="3"}
}
}

3、由匿名类型构成的列表和字典

var a1 = new List<dynamic>()  {
new { X = 100, Y = 200 },
new { X = 300, Y = 400}
}; Console.Write(a1[1].X); var moreNumbers = new Dictionary<dynamic, dynamic>
{
{19, "nineteen" },
{23, "twenty-three" },
{42, "forty-two" }
}; Console.Write(moreNumbers[19]);

4、在Linq 中使用

匿名类型通常用在查询表达式的 Select 子句中,以便返回原序列中每个对象的属性子集(Linq 中使用的比较多)。

class MyClass
{
public string Name { set; get; }
public int Number { set; get; }
} void Main()
{
MyClass[] list = new MyClass[12];
var varbj = from obj in list
select new { obj.Name,
                             ID=obj.Number};
foreach (var v in varbj)
{
Console.Writ(v.Name, v.ID);
}
}

5、应用

匿名类型对象的传递

void Main()
{
//匿名类型
var news = new { title = "冰红茶", day = "2019-4-10", author = "康师傅" };
ShowInfo(news);
} static void ShowInfo<T>(T news)
{
dynamic d = news;
Console.WriteLine(d.title);
Console.WriteLine(d.day);
Console.WriteLine(d.author);
}

用匿名类型填充数组,并计算总年龄

var family = new[]                         //使用隐式类型的数组初始化程序
{
new { Name = "Holly", Age = 37 }, //同一个匿名类型连用5次
new { Name = "Jon", Age = 36 },
new { Name = "Tom", Age = 9 },
new { Name = "Robin", Age = 6 },
new { Name = "William", Age = 6 }
}; int totalAge = 0;
foreach (var person in family) //totalAge累加 对每个人使用
{
totalAge += person.Age;
}
Console.WriteLine("Total age: {0}", totalAge);

六、Lambda表示式

(详细见https://www.cnblogs.com/springsnow/p/9441946.html

是一个匿名函数,它可以包含表达式和语句,可用于创建委托或表达式目录树类型。

从 C# 1.0 - 3.0委托示例

///
/// C# 1.0 - 3.0 委托的发展过程
///
public class DelegateEvlove
{
//方法1 定义委托
public delegate void TestDelegate(string s); static void ConsoleStr(string s)
{
Console.WriteLine(s);
} public static void Main(string[] args)
{
//方法1 实例化委托
TestDelegate iDelegate = new TestDelegate(ConsoleStr);
//方法1 调用委托
iDelegate("1 instance delgate"); //方法2 匿名委托
TestDelegate aDelegate = delegate (string s) { Console.WriteLine(s); };
aDelegate("2 anonymous delegate"); //方法3 lambda 表达式
TestDelegate lDelegate = (s) => { Console.WriteLine(s); };
lDelegate("3 lambda delegate"); }
}

1、简单应用

将λ表达式分配给委托类型,同delegate(int x){retun x*x}(匿名函数)

delegate int del(int i);
void Main()
{
del myDel = x => x * x;//或 x=>{return x*x };
int j = myDel(5);
Console.Write(j);
}

2、事件处理程序

当λ表达式有一个输入参数时,括号是可选的。使用空括号指定0个输入参数。也可以显示指定参数类型

public static event EventHandler myEvent;
void Main()
{
myEvent += (s, e) => { Console.Write(s); };
//即myEvent += delegate(object s,EventArgs e) => { Console.Write(s); };
myEvent(this, null);
}

3、创建表达式树类型

using  System.Linq.Expressions;
Expression = x=>x*x;

七、Linq表达式

1、简单应用:

检索所有Sex为false的人,查询结果放到results变量中,results变量与数组persons类型相同

using System.Linq;

var persons = new[] { new { Name = "var", Sex = false }, 
                      new { Name = "var2", Sex = false } };
var results = from p in persons//
              where p.Sex == false
select p;
foreach (var person in results)
{
Console.Write(person.Name);
}

2、嵌套成员:

检索所有城市为伦敦,且订单日期为2018年以后的所有记录,查询结果是一个匿名类型的数组。

var customers = new[] { new { Name = "var",City="China" ,Orders  = new []{new{OrderNO=0,OrderDate=new DateTime(2017,1,1)},
new{OrderNO=1,OrderDate=new DateTime(2018,1,1)}, }},
new { Name = "Vicky",City="London" ,Orders = new []{new{OrderNO=2,OrderDate=new DateTime(2019,9,1)},
new{OrderNO=3,OrderDate=new DateTime(2018,1,1)}, } }
}; var someCustomers = from c in customers
where c.City == "London"
from o in c.Orders
where o.OrderDate.Year > 2018
select new { c.Name, o.OrderNO }; foreach (var customer in someCustomers)
{
Console.Write(customer.Name + customer.OrderNO);
}

八、表达式树

一种有效的数据表达方式,以树的形式显示λ表达式。这些所有数据表达方式可以同时进行编译。

1、如果操作符被声明为可以接受一个方法委托,则编译器将生成IL代码。

public  static IQueryable Where(this IEnumerable source,Func predicate);

2、如果操作符被声明为可以接受一个方法委托“表达式”,则编译器将生成一个表达式树。

public  static IQueryable Where(this IQueryable source,Expression > predicate);

C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数的更多相关文章

  1. C#3.0新增功能06 对象和集合初始值设定项

    连载目录    [已更新最新开发文章,点击查看详细] 使用 C# 可以在单条语句中实例化对象或集合并执行成员分配. 对象初始值设定项 使用对象初始值设定项,你可以在创建对象时向对象的任何可访问字段或属 ...

  2. 从C# 2.0新特性到C# 3.5新特性

    一.C# 2.0 新特性: 1.泛型 List<MyObject> obj_list=new List(); obj_list.Add(new MyObject()); 2.部分类(par ...

  3. C# 9.0 新特性预览 - 类型推导的 new

    C# 9.0 新特性预览 - 类型推导的 new 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大 ...

  4. [翻译] C# 8.0 新特性 Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南) 【由浅至深】redis 实现发布订阅的几种方式 .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐

    [翻译] C# 8.0 新特性 2018-11-13 17:04 by Rwing, 1179 阅读, 24 评论, 收藏, 编辑 原文: Building C# 8.0[译注:原文主标题如此,但内容 ...

  5. C#6.0,C#7.0新特性

    C#6.0新特性 Auto-Property enhancements(自动属性增强) Read-only auto-properties (真正的只读属性) Auto-Property Initia ...

  6. C#7.0&6.0新特性 — 完整版

    C#2.0 泛型 部分类型 匿名方法 迭代器 可空类型 Getter / setter单独可访问性 方法组转换(代表) Co- and Contra-variance for delegates 静态 ...

  7. [转] Scala 2.10.0 新特性之字符串插值

    [From]  https://unmi.cc/scala-2-10-0-feature-string-interpolation/ Scala 2.10.0 新特性之字符串插值 2013-01-20 ...

  8. Android 7.0新特性

    还望支持个人博客站:http://www.enjoytoday.cn 由于google目前不是无法直接在国内访问,故此,对于android 开发平台的7.0新特性做个保存.也可供大家查阅.原文转自an ...

  9. C# 9.0 新特性预览 - 空参数校验

    C# 9.0 新特性预览 - 空参数校验 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它 ...

随机推荐

  1. 剑指offer(26-30)编程题

    二叉搜索树与双向链表 字符串的排列 数组中出现次数超过一半的数字 最小的K个数 连续子数组的最大和 26.输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整 ...

  2. Nexus centos 安装

    目录 1.安装nexus 2.启动nexus 2.1启动服务器 2.2以后台进程启动: 2.3web访问 3.搭建私服 3.1 界面元素介绍 3.2 仓库集合的界面 3.3 通过网页方式将jar包上传 ...

  3. ACM,算法

    ACM,算法 描述 最近Topcoder的XD遇到了一个难题,倘若一个数的三次方的后三位是111,他把这样的数称为小光棍数.他已经知道了第一个小光棍数是471,471的三次方是104487111,现在 ...

  4. nodejs学习笔记三(用户注册、登录)

    1.定接口      /user 接口               输入    act=reg&user=aaa&pass=123456               输出     {& ...

  5. 跨域 cookies

    script标签请求的js脚本,如果跨域了,请求会带有外域的cookies信息. XMLHttpRequest请求跨域时,需要有Access-Control-*等的头信息,如果需要将cookies传输 ...

  6. RabbitMQ---5、qos内存溢出+prefetch消息堵塞问题

    1.prefetch消息堵塞问题 mq是实现代码扩展的有利手段,个人喜欢用概念来学习新知识,介绍堵塞问题的之前,先来段概念的学习. ConnectionFactory:创建connection的工厂类 ...

  7. npm(cnpm)介绍(安装gulp)

    1.npm(node package manager) nodejs的包管理器,用于node插件管理(安装.卸载.更新.管理依赖等); 2.使用npm安装安装插件: 1).命令提示符执行 npm in ...

  8. 使用jQuery获取Dribbble的内容

    Introduction As a web developer, third party API integration is something you will have to face. Esp ...

  9. 常用SEO优化

  10. 一键清理 Nexus 中无用的 Docker 镜像

    现许多团队使用 Nexus 来管理 Docker 镜像,产品不断迭代,镜像仓库占用的磁盘空间也越来越大.由于 Nexus 的控制台并未提供批量操作镜像功能,清理镜像十分不便.本文分享一个清理 Nexu ...