LINQ体验(2)——C# 3.0新语言特性和改进(上篇)
整体来说。Visual Studio 2008和.NET 3.5是建立在.NET2.0核心的基础之上,.NET2.0核心本身将不再变化(假设不了解.NET2.0的朋友,请參看MSDN或者一些经典的书籍),C# 3.0新语言特性在.NET2.初级上进行了改进,这些改进的功能能够大大简化我们编敲代码。关于C# 3.0新语言特性在博客园里的非常多朋友都介绍了,我在这里简介一下,记录自己所学的东西,也为后面的LINQ打下基础。
C# 3.0新语言特性和改进包含:
- 自己主动属性(Auto-Implemented Properties)
- 隐含类型局部变量(Local Variable Type Inference)
- 匿名类型(Anonymous Types)
- 对象与集合初始化器(Object and Collection Initializers)
- 扩展方法(Extension Methods)
- Lambda表达式和Lambda表达式树 (Lambda Expression and Lambda Expression Trees)
自己主动属性(Auto-Implemented Properties)
自己主动属性能够避免原来这样我们手工声明一个私有成员变量以及编写get/set逻辑,在VS2008中能够像以下这样编写一个类,编译器会自己主动地生成私有变量和默认的get/set 操作。你也能够分别定义get和set的“protected”等訪问级别。
在.Net2.0框架下,我们能够这样写一个User类:
public class User { private int _id; private string _name; private int _age; public int Id { get { return _id; } set { _id = value; } } public string Name { get { return _name; } set { _name = value; } } public int Age { get { return _age; } set { _age = value; } } }
如今,能够这样简化:
public class User { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
像上面这种空的get/set属性的话,它会自己主动为你在类中生成一个私有成员变量。对这个变量实现一个公开的getter 和setter。我们能够使用.NET开发环境所提供的ildasm.exe(IL代码反汇编器)工具来分析程序集或者模块的内容。
我就不贴图了。
隐含类型局部变量(Local Variable Type Inference)
C#3.0引进了var这个新keyword。在声明局部变量时可用于替代原先的类型名。即当一个变量声明标识为var类型而且该范围域中没有var名称类型存在。那么这个声明就称为隐含类型局部变量。例如以下(等同于//后面的显式声明):
var i = 5;//int var j = 23.56;//double var k = "C Sharp";//string var x;//错误 var y = null;//错误 var z = { 1, 2, 3 };//错误
在调试状态下。编译器解释例如以下
隐含类型局部变量要点
- var为keyword。能够依据后面的初始化语句自己主动判断类型,这个类型为强类型。
- 初始化语句必须为表达式,不能够为空。且编译时能够判断类型。一旦初始化之后,仅仅能够存储这样的类型。
- var声明的仅限于局部变量。不可用于字段。
亦能够用于for。foreach,using 等语句中。
- 数组也能够作为隐含类型。
- 初始化语句不能是一个自身的对象或者集合初始化器。可是他能够是包括一个对象或者初始化器的一个new表达式。
- 假设局部变量声明包括了多个声明符,其类型必须同样。
匿名类型(Anonymous Types)
匿名类型同意定义行内类型。无须显式定义类型。
常和var配合使用来声明匿名类型。
var p1 = new { Id = 1, Name = "YJingLee", Age = 22 };//属性也不须要申明 var p2 = new { Id = 2, Name = "XieQing", Age = 25 }; p1 = p2;//p1,p2结构同样,能够互相赋值
在这里编译器会觉得p1,p2相当于:
public class SomeType { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
那么数组怎么定义呢?使用"new[]"keyword来声明数组。加上数组的初始值列表。像这样:
var intArray = new[] { 2, 3, 5, 6 }; var strArray = new[] { "Hello", "World" }; var anonymousTypeArray = new[] { new { Name = "YJingLee", Age = 22 }, new { Name = "XieQing", Age = 25 } }; var a = intArray[0]; var b = strArray[0]; var c = anonymousTypeArray[1].Name;
匿名类型要点
- 能够使用newkeyword调用匿名初始化器创建一个匿名类型的对象。
- 匿名类型直接继承自System. Object。
- 匿名类型的成员是编译器依据初始化器判断而来的一些读写属性。
对象与集合初始化器(Object and Collection Initializers)
对象初始化器 (Object Initializers) :
.NET2.0框架中的类型很依赖于属性。当生成对象实例和使用新的类型时,在.Net2.0时候我们像这样写:
User user = new User(); user.Id = 1; user.Name = "YJingLee"; user.Age = 22;
在VS2008中,编译器会自己主动地生成合适的属性setter代码,使得原来几行的属性赋值操作能够在一行完毕。
我们能够这样简化:像这样,对象初始化器由一系列成员对象组成,其对象必须初始化,用逗号间隔。使用{}封闭。
User user = new User { Id = 1, Name = "YJingLee", Age = 22 };
又比如。我把二个人加到一个基于泛型的类型为User的List集合中:
List<User> user = new List<User>{ new User{Id=1,Name="YJingLee",Age=22}, new User{Id=2,Name="XieQing",Age=25}, };
假设有同样名字和类型的两个对象初始化器将会产生同样的实例,能够相互赋值。
比如:
User user = new User { Id = 1, Name = "YJingLee", Age = 22 }; User user2 = new User { Id = 2, Name = "XieQing", Age = 25 }; user = user2;
除了在初始化类时设置简单的属性值外。对象初始化器特性也同意我们设置更复杂的嵌套(nested)属性类型。比如我们能够在上面定义的User类型同一时候拥有一个属于Address类型的叫“Address”的属性:
User user = new User { Id = 1, Name = "YJingLee", Age = 22, Address = new Address { City = "NanJing", Zip = 21000 } };
集合初始化器(Collection Initializers):
集合初始化器由一系列集合对象组成,用逗号间隔,使用{}封闭。
集合初始化器能够简化把几个对象一起加入到一个集合。编译器会自己主动为你做集合插入操作。比如我把七个数加到一个基于泛型的类型为int的List集合中
List<int> num = new List<int> { 0, 1, 2, 6, 7, 8, 9 };
对象与集合初始化器要点
- 对象初始化器实际上利用了编译器对对象中对外可见的字段和属性进行按序赋值。
- 对象初始化器同意仅仅给一部分属性赋值,包含internal訪问级别
- 对象初始化器能够结合构造函数一起使用,而且构造函数初始化先于对象初始化器运行。
- 集合初始化器会对初始化器中的元素进行按序调用ICollection<T>.Add(T)方法。
- 注意对象初始化器和集合初始化器中成员的可见性和调用顺序。
- 对象与集合初始化器相同是一种编译时技术。