匿名类

匿名类就一个没有名称的类,它同样继承自Object。匿名类通常和var、new一起使用,例如,我们需要定义一个对象,该对象中包含姓名、年龄、性别3个字段:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var person = new { Name = "CS", Age = 20, Gender = true };
 6             Console.WriteLine(person.GetType().Name);//<>f__AnonymousType0`3
 7 
 8             Console.ReadKey();
 9         }
10     }

我们通过ILDasm反编译程序集,通过IL代码看一下匿名类的真面目:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 代码大小       39 (0x27)
  .maxstack  3
  .locals init ([0] class '<>f__AnonymousType0`3'<string,int32,bool> person)
  IL_0000:  nop
  IL_0001:  ldstr      "CS"
  IL_0006:  ldc.i4.s   20
  IL_0008:  ldc.i4.1
  IL_0009:  newobj     instance void class '<>f__AnonymousType0`3'<string,int32,bool>::.ctor(!0,
                                                                                             !1,
                                                                                             !2)
  IL_000e:  stloc.0
  IL_000f:  ldloc.0
  IL_0010:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_0015:  callvirt   instance string [mscorlib]System.Reflection.MemberInfo::get_Name()
  IL_001a:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_001f:  nop
  IL_0020:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_0025:  pop
  IL_0026:  ret
} // end of method Program::Main

 从IL代码可以看出来,person对象实际上是泛型类<>f__AnonymousType0`3的一个对象,Console.WriteLine(person.GetType().Name);也对其进行了验证,也就是说匿名类的本质是一个泛型类,并且匿名类的属性是只读的。

匿名类可以用于在线程间传递数据,因为它的属性是只读的。

我们在看下面的代码:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var person1 = new { Name = "CS", Age = 20, Gender = true };
 6             var person2 = new { Name = "CS", Age = 23, Gender = false };
 7             var person3 = new { Age = 20, Name = "CS", Gender = true };
 8             var person4 = new { Name = "CS", Age = 20, Gender = "" };
 9             var person5 = new { Name = "CS", Age = 20, Gender = true, Address = "HN" };
10             Console.WriteLine(person1.GetType() == person2.GetType());//True
11             Console.WriteLine(person1.GetType() == person3.GetType());//False
12             Console.WriteLine(person1.GetType() == person4.GetType());//False
13             Console.WriteLine(person1.GetType() == person5.GetType());//False
14 
15             Console.ReadKey();
16         }
17     }

我们同样通过IL代码来看一下,编译器为我们做了哪些工作:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 代码大小       181 (0xb5)
  .maxstack  4
  .locals init ([0] class '<>f__AnonymousType0`3'<string,int32,bool> person1,
           [1] class '<>f__AnonymousType0`3'<string,int32,bool> person2,
           [2] class '<>f__AnonymousType1`3'<int32,string,bool> person3,
           [3] class '<>f__AnonymousType0`3'<string,int32,string> person4,
           [4] class '<>f__AnonymousType2`4'<string,int32,bool,string> person5)
  IL_0000:  nop
  IL_0001:  ldstr      "CS"
  IL_0006:  ldc.i4.s   20
  IL_0008:  ldc.i4.1
  IL_0009:  newobj     instance void class '<>f__AnonymousType0`3'<string,int32,bool>::.ctor(!0,
                                                                                             !1,
                                                                                             !2)
  IL_000e:  stloc.0
  IL_000f:  ldstr      "CS"
  IL_0014:  ldc.i4.s   23
  IL_0016:  ldc.i4.0
  IL_0017:  newobj     instance void class '<>f__AnonymousType0`3'<string,int32,bool>::.ctor(!0,
                                                                                             !1,
                                                                                             !2)
  IL_001c:  stloc.1
  IL_001d:  ldc.i4.s   20
  IL_001f:  ldstr      "CS"
  IL_0024:  ldc.i4.1
  IL_0025:  newobj     instance void class '<>f__AnonymousType1`3'<int32,string,bool>::.ctor(!0,
                                                                                             !1,
                                                                                             !2)
  IL_002a:  stloc.2
  IL_002b:  ldstr      "CS"
  IL_0030:  ldc.i4.s   20
  IL_0032:  ldstr      bytearray (37 75 )                                           // 7u
  IL_0037:  newobj     instance void class '<>f__AnonymousType0`3'<string,int32,string>::.ctor(!0,
                                                                                               !1,
                                                                                               !2)
  IL_003c:  stloc.3
  IL_003d:  ldstr      "CS"
  IL_0042:  ldc.i4.s   20
  IL_0044:  ldc.i4.1
  IL_0045:  ldstr      "HN"
  IL_004a:  newobj     instance void class '<>f__AnonymousType2`4'<string,int32,bool,string>::.ctor(!0,
                                                                                                    !1,
                                                                                                    !2,
                                                                                                    !3)
  IL_004f:  stloc.s    person5
  IL_0051:  ldloc.0
  IL_0052:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_0057:  ldloc.1
  IL_0058:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_005d:  call       bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
                                                               class [mscorlib]System.Type)
  IL_0062:  call       void [mscorlib]System.Console::WriteLine(bool)
  IL_0067:  nop
  IL_0068:  ldloc.0
  IL_0069:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_006e:  ldloc.2
  IL_006f:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_0074:  call       bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
                                                               class [mscorlib]System.Type)
  IL_0079:  call       void [mscorlib]System.Console::WriteLine(bool)
  IL_007e:  nop
  IL_007f:  ldloc.0
  IL_0080:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_0085:  ldloc.3
  IL_0086:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_008b:  call       bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
                                                               class [mscorlib]System.Type)
  IL_0090:  call       void [mscorlib]System.Console::WriteLine(bool)
  IL_0095:  nop
  IL_0096:  ldloc.0
  IL_0097:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_009c:  ldloc.s    person5
  IL_009e:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_00a3:  call       bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
                                                               class [mscorlib]System.Type)
  IL_00a8:  call       void [mscorlib]System.Console::WriteLine(bool)
  IL_00ad:  nop
  IL_00ae:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_00b3:  pop
  IL_00b4:  ret
} // end of method Program::Main

上面的代码中,我们声明了5个匿名类的对象,我们先看person1和person2两个对象,这两个对象包含的字段名称一样,只是值不一样,那么对象person1和person2就是同一个泛型类(<>f__AnonymousType0`3)的对象,并且我们他们的泛型参数类型都是string,int32,bool,所以最后的Console.WriteLine(person1.GetType() == person2.GetType());的结果是True。person1和person2是同一个泛型类的对象,并且泛型参数类型一样。

 

person1和person3两个对象虽然都具有Name、Age、Gender这3个字段名称,但是由于字段名称不一样(其实我就是将字段的先后顺序改变了一下,这个地方说的字段名称不一样指的是person1中的第一个参数名称为Name,person3中的第一个参数名称为Age,两个字段名称不一样),导致person1和person3属于了两个不同的泛型类的对象,从IL代码中我们可以看出,person1是泛型类<>f__AnonymousType0`3的一个对象,并且泛型参数类型是string,int32,bool;而person3是泛型类<>f__AnonymousType1`3的一个对象,泛型参数类型为int32,string,bool,所以最后的Console.WriteLine(person1.GetType() == person2.GetType());的结果是False。person1和person不是同一个泛型类的对象,并且泛型参数类型不一样。

 

person1和person4两个对象具有3个相同的字段名称,从IL代码来看person1和person4是同一个泛型类<>f__AnonymousType0`3的对象,但是为什么最后Console.WriteLine(person1.GetType() == person4.GetType());的值为False呢?原因是,虽然person1和person4属于同一个泛型类的对象,但是对象的泛型参数类型却是不同的,person1的泛型参数类型为string,int32,bool;而person4的泛型参数类型为string,int32,string;所以最后的输出结果为False。person1和person4是同一个泛型类的对象,但是泛型参数类型不一样。

 

person1和person5两个对象,我们根据前边的知识,不用看IL代码就应该知道他们肯定不是同一个泛型类的对象,因为它们的字段个数都不一样,person1是泛型类<>f__AnonymousType0`3的一个对象,泛型参数类型为string,int32,bool;而person5是泛型类<>f__AnonymousType2`4的一个对象,泛型参数类型为string,int32,bool,string;语句Console.WriteLine(person1.GetType() == person5.GetType());的执行结果为False。person1和person5不是同一个泛型类的对象,并且泛型参数类型不一样。

 

posted @ 2017-06-19 21:54  CS讷于言而敏于行  阅读(266)  评论(0编辑  收藏  举报