C# 匿名类
[ C# 3.0/.NET 3.x 新增特性 ]
1.1 不好意思,我匿了
在开发中,我们有时会像下面的代码一样声明一个匿名类:可以看出,在匿名类的语法中并没有为其命名,而是直接的一个new { }就完事了。从外部看来,我们根本无法知道这个类是干神马的,也不知道它有何作用。
var annoyCla1 = new { ID = 10010, Name = "EdisonChou", Age = 25 }; Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla1.ID,annoyCla1.Name, annoyCla1.Age);
经过调试运行,我们发现匿名类完全可以实现具名类的效果:
1.2 深入匿名类背后
既然我们发现匿名类可以完全实现具名类的效果,那么我们可以大胆猜测编译器肯定在内部帮我们生成了一个类似具名类的class,于是,我们还是借助反编译工具对其进行探索。通过Reflector反编译,我们找到了编译器生成的匿名类如下图所示:
从上图可以看出:
(1)匿名类被编译后会生成一个[泛型类],可以看到上图中的<>f__AnonymousType0<<ID>j__TPar, <Name>j__TPar, <Age>j__TPar>就是一个泛型类;
(2)匿名类所生成的属性都是只读的,可以看出与其对应的字段也是只读的;
所以,如果我们在程序中为属性赋值,那么会出现错误;
(3)可以看出,匿名类还重写了基类的三个方法:Equals,GetHashCode和ToString;我们可以看看它为我们所生成的ToString方法是怎么来实现的:
实现的效果如下图所示:
1.3 匿名类的共享
可以想象一下,如果我们的代码中定义了很多匿名类,那么是不是编译器会为每一个匿名类都生成一个泛型类呢?答案是否定的,编译器考虑得很远,避免了重复地生成类型。换句话说,定义了多个匿名类的话如果符合一定条件则可以共享一个泛型类。下面,我们就来看看有哪几种情况:
(1)如果定义的匿名类与之前定义过的一模一样:属性类型和顺序都一致,那么默认共享前一个泛型类
var annoyCla1 = new { ID = 10010, Name = "EdisonChou", Age = 25 }; Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla1.ID, annoyCla1.Name, annoyCla1.Age); Console.WriteLine(annoyCla1.ToString()); // 02.属性类型和顺序与annoyCla1一致,那么共同使用一个匿名类 var annoyCla2 = new { ID = 10086, Name = "WncudChou", Age = 25 }; Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla1.ID, annoyCla1.Name, annoyCla1.Age); Console.WriteLine("Is The Same Class of 1 and 2:{0}", annoyCla1.GetType() == annoyCla2.GetType());
通过上述代码中的最后两行:我们可以判断其是否是一个类型?答案是:True
(2)如果属性名称和顺序一致,但属性类型不同,那么还是共同使用一个泛型类,只是泛型参数改变了而已,所以在运行时会生成不同的类:
var annoyCla3 = new { ID = "EdisonChou", Name = 10010, Age = 25 }; Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla3.ID, annoyCla3.Name, annoyCla3.Age); Console.WriteLine("Is The Same Class of 2 and 3:{0}", annoyCla3.GetType() == annoyCla2.GetType());
我们刚刚说到虽然共享了同一个泛型类,只是泛型参数改变了而已,所以在运行时会生成不同的类。所以,那么可以猜测到最后两行代码所显示的结果应该是False,他们虽然都使用了一个泛型类,但是在运行时生成了两个不同的类。
(3)如果数据型名称和类型相同,但顺序不同,那么编译器会重新创建一个匿名类
var annoyCla4 = new { Name = "EdisonChou", ID = 10010, Age = 25 }; Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla4.ID, annoyCla4.Name, annoyCla4.Age); Console.WriteLine("Is The Same Class of 2 and 4:{0}", annoyCla4.GetType() == annoyCla2.GetType());
运行判断结果为:False
通过Reflector,可以发现,编译器确实重新生成了一个泛型类:
出处:http://edisonchou.cnblogs.com