一、定义
使用关键字var和对象初始化器来生成一个匿名类型。
二、匿名类型的内部表示
其实为对象生成了若干只读属性
三、ToString() 和 GetHashCode()的实现
所有的匿名类型自动继承自System.Object ,并且重写了Equals(), GetHashCode(), and ToString().
ToString(). 只是简单的用 属性名称/属性值 构造了一个字符串
GetHashCode() 实现时,根据匿名类型的每个成员作为System.Collections.Generic.EqualityComparer<T>的输入,来计算hash值。
因此,如果2个匿名类型有相同的属性字段,同时每个字段的值也相同,那么生成的Hash值也就相等。
三、匿名类型的相等
输出结果:
Equals() 结果相等,因为它使用值来比较相等,比如,比较每个字段的值是否显等
== 结果不等,因为匿名类型没有重载 == 和 != , 这两个操作符默认情况下,比较的是对象的引用而不是成员的值。
最后,在一个程序集中(assembly),如果你定义多个字段完全相同的匿名类型对象,编译器只会生成一个匿名类型,这些对象都是该唯一的匿名类型的实例。
四、在匿名类型中定义匿名类型
五、匿名类型的使用条件
应该尽量少用匿名类型,只在LINQ中使用
• You don’t control the name of the anonymous type.
• Anonymous types always extend System.Object.
• The fields and properties of an anonymous type are always read-only.
• Anonymous types cannot support events, custom methods, custom operators, or custom
overrides.
• Anonymous types are always implicitly sealed.
• Anonymous types are always created using the default constructor.
使用关键字var和对象初始化器来生成一个匿名类型。
// Make an anonymous type representing a car.
var myCar = new { Color = "Bright Pink", Make = "Saab", CurrentSpeed = 55 };
// Now show the color and make.
Console.WriteLine("My car is a {0} {1}.", myCar.Color, myCar.Make);
var myCar = new { Color = "Bright Pink", Make = "Saab", CurrentSpeed = 55 };
// Now show the color and make.
Console.WriteLine("My car is a {0} {1}.", myCar.Color, myCar.Make);
二、匿名类型的内部表示
static void ReflectOverAnonymousType(object obj)
{
Console.WriteLine("obj is an instance of: {0}", obj.GetType().Name);
Console.WriteLine("Base class of {0} is {1}",
obj.GetType().Name,
obj.GetType().BaseType);
Console.WriteLine("obj.ToString() = {0}", obj.ToString());
Console.WriteLine("obj.GetHashCode() = {0}", obj.GetHashCode());
Console.WriteLine();
}
{
Console.WriteLine("obj is an instance of: {0}", obj.GetType().Name);
Console.WriteLine("Base class of {0} is {1}",
obj.GetType().Name,
obj.GetType().BaseType);
Console.WriteLine("obj.ToString() = {0}", obj.ToString());
Console.WriteLine("obj.GetHashCode() = {0}", obj.GetHashCode());
Console.WriteLine();
}
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Anonymous types *****\n");
// Make an anonymous type representing a car.
var myCar = new {Color = "Bright Pink", Make = "Saab", CurrentSpeed = 55};
// Reflect over what the compiler generated.
ReflectOverAnonymousType(myCar);
Console.ReadLine();
}
{
Console.WriteLine("***** Fun with Anonymous types *****\n");
// Make an anonymous type representing a car.
var myCar = new {Color = "Bright Pink", Make = "Saab", CurrentSpeed = 55};
// Reflect over what the compiler generated.
ReflectOverAnonymousType(myCar);
Console.ReadLine();
}
其实为对象生成了若干只读属性
internal sealed class <>f__AnonymousType0<<Color>j__TPar,
<Make>j__TPar, <CurrentSpeed>j__TPar>
{
// Read-only fields
private readonly <Color>j__TPar <Color>i__Field;
private readonly <CurrentSpeed>j__TPar <CurrentSpeed>i__Field;
private readonly <Make>j__TPar <Make>i__Field;
// Default constructor
public <>f__AnonymousType0(<Color>j__TPar Color,
<Make>j__TPar Make, <CurrentSpeed>j__TPar CurrentSpeed);
// Overridden methods
public override bool Equals(object value);
public override int GetHashCode();
public override string ToString();
// Read-only properties
public <Color>j__TPar Color { get; }
public <CurrentSpeed>j__TPar CurrentSpeed { get; }
public <Make>j__TPar Make { get; }
}
<Make>j__TPar, <CurrentSpeed>j__TPar>
{
// Read-only fields
private readonly <Color>j__TPar <Color>i__Field;
private readonly <CurrentSpeed>j__TPar <CurrentSpeed>i__Field;
private readonly <Make>j__TPar <Make>i__Field;
// Default constructor
public <>f__AnonymousType0(<Color>j__TPar Color,
<Make>j__TPar Make, <CurrentSpeed>j__TPar CurrentSpeed);
// Overridden methods
public override bool Equals(object value);
public override int GetHashCode();
public override string ToString();
// Read-only properties
public <Color>j__TPar Color { get; }
public <CurrentSpeed>j__TPar CurrentSpeed { get; }
public <Make>j__TPar Make { get; }
}
三、ToString() 和 GetHashCode()的实现
所有的匿名类型自动继承自System.Object ,并且重写了Equals(), GetHashCode(), and ToString().
ToString(). 只是简单的用 属性名称/属性值 构造了一个字符串
public override string ToString()
{
StringBuilder builder = new StringBuilder();
builder.Append("{ Color = ");
builder.Append(this.<Color>i__Field);
builder.Append(", Make = ");
builder.Append(this.<Make>i__Field);
builder.Append(", CurrentSpeed = ");
builder.Append(this.<CurrentSpeed>i__Field);
builder.Append(" }");
return builder.ToString();
}
{
StringBuilder builder = new StringBuilder();
builder.Append("{ Color = ");
builder.Append(this.<Color>i__Field);
builder.Append(", Make = ");
builder.Append(this.<Make>i__Field);
builder.Append(", CurrentSpeed = ");
builder.Append(this.<CurrentSpeed>i__Field);
builder.Append(" }");
return builder.ToString();
}
GetHashCode() 实现时,根据匿名类型的每个成员作为System.Collections.Generic.EqualityComparer<T>的输入,来计算hash值。
因此,如果2个匿名类型有相同的属性字段,同时每个字段的值也相同,那么生成的Hash值也就相等。
三、匿名类型的相等
static void EqualityTest()
{
// Make 2 anonymous classes with identical name/value pairs.
var firstCar = new { Color = "Bright Pink", Make = "Saab", CurrentSpeed = 55 };
var secondCar = new { Color = "Bright Pink", Make = "Saab", CurrentSpeed = 55 };
// Are they considered equal when using Equals()?
if (firstCar.Equals(secondCar))
Console.WriteLine("Same anonymous object!");
else
Console.WriteLine("Not the same anonymous object!");
// Are they considered equal when using ==?
if (firstCar == secondCar)
Console.WriteLine("Same anonymous object!");
else
Console.WriteLine("Not the same anonymous object!");
// Are these objects the same underlying type?
if (firstCar.GetType().Name == secondCar.GetType().Name)
Console.WriteLine("We are both the same type!");
else
Console.WriteLine("We are different types!");
// Show all the details.
Console.WriteLine();
ReflectOverAnonymousType(firstCar);
ReflectOverAnonymousType(secondCar);
}
{
// Make 2 anonymous classes with identical name/value pairs.
var firstCar = new { Color = "Bright Pink", Make = "Saab", CurrentSpeed = 55 };
var secondCar = new { Color = "Bright Pink", Make = "Saab", CurrentSpeed = 55 };
// Are they considered equal when using Equals()?
if (firstCar.Equals(secondCar))
Console.WriteLine("Same anonymous object!");
else
Console.WriteLine("Not the same anonymous object!");
// Are they considered equal when using ==?
if (firstCar == secondCar)
Console.WriteLine("Same anonymous object!");
else
Console.WriteLine("Not the same anonymous object!");
// Are these objects the same underlying type?
if (firstCar.GetType().Name == secondCar.GetType().Name)
Console.WriteLine("We are both the same type!");
else
Console.WriteLine("We are different types!");
// Show all the details.
Console.WriteLine();
ReflectOverAnonymousType(firstCar);
ReflectOverAnonymousType(secondCar);
}
输出结果:
Equals() 结果相等,因为它使用值来比较相等,比如,比较每个字段的值是否显等
== 结果不等,因为匿名类型没有重载 == 和 != , 这两个操作符默认情况下,比较的是对象的引用而不是成员的值。
最后,在一个程序集中(assembly),如果你定义多个字段完全相同的匿名类型对象,编译器只会生成一个匿名类型,这些对象都是该唯一的匿名类型的实例。
四、在匿名类型中定义匿名类型
// Make an anonymous type that is composed of another.
var purchaseItem = new {
TimeBought = DateTime.Now,
ItemBought = new {Color = "Red", Make = "Saab", CurrentSpeed = 55},
Price = 34.000};
ReflectOverAnonymousType(purchaseItem);
var purchaseItem = new {
TimeBought = DateTime.Now,
ItemBought = new {Color = "Red", Make = "Saab", CurrentSpeed = 55},
Price = 34.000};
ReflectOverAnonymousType(purchaseItem);
五、匿名类型的使用条件
应该尽量少用匿名类型,只在LINQ中使用
• You don’t control the name of the anonymous type.
• Anonymous types always extend System.Object.
• The fields and properties of an anonymous type are always read-only.
• Anonymous types cannot support events, custom methods, custom operators, or custom
overrides.
• Anonymous types are always implicitly sealed.
• Anonymous types are always created using the default constructor.