LINQ技术的基础 - C#3.0
-
自动属性
-
隐式类型
-
对象集合初始化器
-
匿名类
-
扩展方法
-
Lambda表达式
自动属性
这个概念很简单,其简化了我们在.NET的时候手写一堆私有成员+属性的编程方式,我们只需要使用如下方式声明一个属性,编译器会自动生成所需的成员变量。
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
在我使用LINQ完成的项目中,使我了解到自动属性方便的一个用途如下:
在使用LINQ获取数据的过程中,我们常常需要使用select new语句查询出一个对象(往往是IEnumerable类型的)用于数据绑定。在一般情况下如果是直接绑定(如直接将查询结果赋给一个Gridview控件的DataSource属性)我们可以直接select new来返回一个匿名类的对象。如果我们还需要对这个集合对象进行进一步操作,我们将必须使用select new class-name这样的语言返回一个类的对象,大部分情况下这个类只作为实体的一个结构而不需要完成一些操作操作,这时候使用自动属性来完成这个类将是非常简洁高效的。
隐式类型
这个名称可能对你很陌生,但是var这个关键字应该都用过,在C#中使用var声明一个对象时,编译器会自动根据其赋值语句推断这个局部变量的类型。赋值以后,这个变量的类型也就确定而不可以再进行更改。另外var关键字也用于匿名类的声明。
应用场合:var主要用途是表示一个LINQ查询的结果。这个结果可能是ObjectQuery<>或IQueryable<>类型的对象,也可能是一个简单的实体类型的对象。这时使用var声明这个对象可以节省很多代码书写上的时间。
对象初始化器与集合初始化器
在.NET2.0中构造一个对象的方法一是提供一个重载的构造函数,二是用默认的构造函数生成一个对象,然后对其属性进行赋值。在.NET3.5/C#3.0中我们有一种更好的方式来进行对象的初始化。那就是使用对象初始化器。这个特性也是匿名类的一个基础,所以放在匿名类之前介绍。
还是那就话,好的代码强于注释,下面用几个代码段说明初始化器:
基本用法:
User user = new User { Id = 1, Name = "YJingLee", Age = 22 };
嵌套使用:
User user = new User
{
Id = 1,
Name = "YJingLee",
Age = 22,
Address = new Address
{
City = "NanJing",
Zip = 21000
}
};
类似于对象初始化器初始化一个对象,集合初始化器初始化一个集合,一句话,有了它你就不用在将元素通过Add逐个添加了。仍然给出代码示例:
基本使用:
List<int> num = new List<int> { 0, 1, 2, 6, 7, 8, 9 };
结合对象初始化器,我们可以写出如下简洁的代码:
List<User> user = new List<User>{
new User{Id=1,Name="YJingLee",Age=22},
new User{Id=2,Name="XieQing",Age=25},
};
应用场合:
还是前文提到的select new class-name语法,后面可以直接接一个初始化器来将查询结果返回到这个对象。
匿名类
有了前文初始化器的介绍,匿名类就很简单了。我们可以使用new { object initializer }或new[]{ object, …}来初始化一个匿名类或不确定类型的数组。匿名类的对象需要使用var关键字声明。示例代码:
var p1 = new { Id = 1, Name = "YJingLee", Age = 22 };
应用场合:
还是同上面的例子提到的当直接使用select new { object initializer }这样的语法就是将一个LINQ查询的结果返回到一个匿名类中。
扩展方法
扩展方法是C#中新增的很重要的特性之一。其对于LINQ的实现起着关键的作用。在.NET2.0时代是没有LINQ的,所以.NET2.0以及之前版本中的集合类在设计的时候没有预留用于LINQ的方法。为了在不破坏这个类现有封装的前提下又可以为其添加LINQ的支持就需要用到扩展方法。
扩展方法使用上类似于静态方法,但在本质上其是实例方法。这是由于.NET3.5的运行环境仍然为CLR2.0所以语言不可能做很大的变革,这一切都是语法糖。
下面仍然通过一段代码来说明扩展方法的实现:
public static class Extensions
{
public static bool IsValidEmailAddress(this string s)
{
Regex regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
return regex.IsMatch(s);
}
}
如上代码所示,扩展方法为一静态方法,声明于一个静态类,其参数前加上一个this关键字,参数的类型表示这个扩展方法要对这个类型进行扩展。如上述代码表示其要对字符串类型进行扩展。
在应用上扩展方法被作为其扩展的类型的静态方法来调用。如下:
if (email.IsValidEmailAddress())
{
Response.Write("YJingLee提示:这是一个正确的邮件地址");
}
Lambda表达式
Lambda表达式是对.NET2.0中匿名方法在语法形式上的进一步改进,仍然以代码说明:
var inString = list.FindAll(delegate(string s) { return s.Indexof("YJingLee") >= 0; });
使用Lambda表达式代码将更自然易懂。
var inString = list.FindAll(s => s.Indexof("YJingLee") >= 0);
可以看出,Lambda表达式格式为:(参数列表)=>表达式或语句块
另外我对于Lambda表达式树的概念还不是很明白,有明白的指点一下。