今天主要是对上一节所说的C#3.0的新特性做些补充:对象及集合初始化表达式、匿名类型、局部方法以及查询表达式。这些特性在LINQ中使用也很频繁,尤其是查询表达式。

  1.对象初始化表达式允许开发者在一条语句中给一个对象的一个或多个域或属性进行初始化赋值。这是在C#3.0之后新添加的特性,在这之前只能对C#基本类型或数组进行初始化赋值。示例如下:

(1)自定义类(点和圆):

View Code
 1     //
2 public class Point
3 {
4 //x坐标
5 public int X { get; set; }
6
7 //y坐标
8 public int Y { get; set; }
9 }
10
11 //
12 public class Circle
13 {
14 //半径
15 private double radius;
16 public double Radius
17 {
18 set { radius = value; }
19 get { return radius; }
20 }
21
22 //圆心
23 private Point center;
24 public Point Center
25 {
26 set { center = value; }
27 get { return center; }
28 }
29
30 //计算面积
31 public double Area()
32 {
33 return Math.Pow(radius, 2) * Math.PI;
34 }
35 }

(2)使用对象初始化表达式:

 1         static void Main(string[] args)
2 {
3 //对象初始化表达式
4 Circle circle = new Circle()
5 {
6 Center = new Point()//嵌套对象初始化表达式
7 {
8 X = 10,
9 Y = 10
10 },
11
12 Radius = 5
13 };
14
15 Console.WriteLine("圆面积:"+circle.Area());
16
17 Console.Read();
18 }

(3)结果:

(2)中对象初始化表达式来进行初始化对象和用下述示例代码的初始化编译后的代码是一样的:

1             Circle circle = new Circle();
2 Point center = new Point();
3 center.X = 10;
4 center.Y = 10;
5 //初始化圆心坐标
6 circle.Center = center;
7 //初始化半径
8 circle.Radius = 5;

由此看出对象初始化表达式类似于函数的形式来初始化对象比通过多句代码来初始化要简便得多。

  2.集合初始化表达式允许开发人员在一条语句中初始化一个集合对象,前提集合类型必须实现System.Collection.IEnumerable接口,并实现Add方法。以下我把集合初始化表达式和对象初始化表达相结合起来作为示例来说明:

 1         static void Main(string[] args)
2 {
3 //集合初始化表达式
4 var circles = new List<Circle>
5 {
6 new Circle{Center=new Point{X=1,Y=1},Radius=2},
7 new Circle{Center=new Point{X=2,Y=2},Radius=4},
8 new Circle{Center=new Point{X=3,Y=3},Radius=6},
9 };
10
11 foreach (var c in circles)
12 {
13 Console.WriteLine(string.Format("半径为{0}的圆面积:{1}" ,c.Radius, c.Area()));
14 }
15
16 Console.Read();
17 }

结果:

上述用集合初始化表达式初始化集合对象和下述代码初始化是一样的:

 1             //定义圆对象
2 Circle cir;
3 //定义圆心
4 Point center;
5 //定义圆集合
6 var circles = new List<Circle>();
7
8 //初始化圆
9 cir = new Circle();
10 center = new Point();
11 center.X = 1;
12 center.Y = 1;;
13 cir.Center = center;
14 cir.Radius = 2;
15 //添加圆对象入集合
16 circles.Add(cir);
17
18 cir = new Circle();
19 center = new Point();
20 center.X = 2;
21 center.Y = 2; ;
22 cir.Center = center;
23 cir.Radius = 4;
24 circles.Add(cir);
25
26 cir = new Circle();
27 center = new Point();
28 center.X = 3;
29 center.Y = 3; ;
30 cir.Center = center;
31 cir.Radius = 6;
32 circles.Add(cir);

由此可见使用对象初始化表达式和集合初始化表达式可以大大减少代码的编写。

  3.跟对象初始化表达式一样的方式,可以创建匿名类型,它一般用于在不自定义一个类的前提下,将数据组合成一个对象。如下示例所示:

 1         static void Main(string[] args)
2 {
3   Circle cir1 = new Circle { Center = new Point {X=1,Y=1 },Radius=2 };
4   var cir2=new{Center=new Point {X=1,Y=1 },Radius=2 };//匿名类型
5   var cir3 = new { cir1.Center, cir1.Radius };//匿名类型
6   var cir4 = new { cir1.Radius, cir1.Center };//匿名类型
7
8   Console.WriteLine("匿名对象cir2:{0}", cir2.GetType());
9   Console.WriteLine("匿名对象cir3:{0}", cir3.GetType());
10   Console.WriteLine("匿名对象cir4:{0}", cir4.GetType());
11
12   Console.Read();
13 }

结果:

从结果中可以看到匿名类型会自动创建新类,新类的名称是从对象初始化器本身推断出来的,这种推断的语法叫做初始化投影。另外因为cir2和cir3有相同的字段和属性,且顺序相同,所以两者是相同的匿名类型。而cir4和cir3因为属性的顺序不同,导致编译器产生了不同的匿名类型。

  4.大家都知道在C#中有个关键字Partial(局部),是用来修饰class类的,成为局部类,现在C#3.0语言新添加了Partial Methods(局部方法),它是一个轻量级事件处理机制。局部类和局部方法唯一的关联就是局部方法必须定义在局部类中。并且局部方法的定义和实现可以分开。我用以下示例来具体说明:

(1)声明局部类:

 1      //局部类
2 public partial class PartialClass
3 {
4 //定义局部方法
5 partial void partialMethod();
6
7 public PartialClass()
8 {
9 partialMethod();//调用局部方法
10 }
11
12 }
13
14 //局部类
15 public partial class PartialClass
16 {
17 //局部方法实现部分
18 partial void partialMethod()
19 {
20 Console.WriteLine("调用局部方法");
21 }
22 }

(2)建立局部类对象:

View Code
1         static void Main(string[] args)
2 {
3 PartialClass pc = new PartialClass();
4
5 Console.Read();
6 }

(3)结果:

不仅局部方法的定义和实现可以分开,甚至只有方法的定义没有方法的实现也可以。只不过在这种情况下,编译器在编译局部代码时不会产生任何IL(中间代码)代码,就像方法不存在一样。把上述代码中的局部方法实现部分去掉:

 1      //局部类
2 public partial class PartialClass
3 {
4 //定义局部方法
5 partial void partialMethod();
6
7 public PartialClass()
8 {
9 partialMethod();//调用局部方法
10 }
11
12 }

就不会产生任何的输出结果。局部方法被Linq To SQL作为一种轻量级事件来处理。在Linq To SQL自动生成的实体类中,每一个与数据库中字段相对应的属性值在修改之前会自动调用局部方法,在修改之后又会调用另一个局部方法。作为开发人员可以自己定义这两个局部方法的实现代码,当然也可以不定义实现部分,这本质上类似于一种事件处理机制。现对局部方法总结如下:(1)局部方法只能定义和实现在局部类中;(2)局部方法需用关键字partial来修饰;(3)局部方法是私有的,但不能用private来修饰;(4)局部方法的返回值必须为void;(5)局部方法可以没有实现部分;(6)局部方法可以是静态的;(7)局部方法可以有参数;

  5.最后来说说查询表达式,它也是LINQ使许多开发人员爱不释手的原因之一。并且查询表达式包括许多之前讲到过的C#3.0语言新的特性。示例如下:

 1         static void Main(string[] args)
2 {
3 var Sprites = new[]{
4 new {Profession="法师",Weapon="魔杖",Blood=200},
5 new {Profession="战士",Weapon="屠龙刀",Blood=1000},
6 new {Profession="导师",Weapon="倚天剑",Blood=500}
7 };
8
9 //查询表达式:查找血量大于300的精灵职业,且按血量的升序排列
10 var query = from s in Sprites
11 where s.Blood > 300
12 orderby s.Blood
13 select new { Profession = s.Profession };
14
15 foreach (var s in query)
16 {
17 Console.WriteLine("血量大于300的精灵职业:{0}", s.Profession);
18 }
19
20 Console.Read();
21 }

结果:

查询表达式以from关键字开始,以select或group关键字结束,from关键字后操作的对象必须实现IEnumerable<T>接口的类的实例。上述的查询表达式还可以写成这样:

1  var query = Sprites
2 .Where(s => s.Blood > 300)
3 .OrderBy(s => s.Blood)
4 .Select(s => new { Profession = s.Profession });

前者通过编译器翻译后生成上述这样等价的语句,所以查询表达式包括Lamdba表达式、扩展方法(如:Where和OrderBy方法)、对象初始化表达式、匿名类型和局部类型推断var等。因为查询表达式是LINQ技术中是最常用的,所这些C#3.0的新特性是LINQ技术底层实现的基础。因此掌握了这些C#语言特性在之后进一步学习LINQ就会显得轻松许多。

作者: Rookie_J 发表于 2011-08-29 14:15 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"