C#匿名类型(AnonymousType)学习日记
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C#匿名类型(AnonymousType)学习⽇记
当我们不要定义复杂的⽅法,事件,构造函数这样复杂的类的时候,可以动态的⽣成⼀个⾃定义的数据类型 --> 匿名类型。
1.定义匿名类型
定义⼀个匿名类型时,需要⽤到 var 关键字和对象初始化语法。
var : 编译器会在编译时⾃动⽣成新类定义(我们⽆法在C#代码中看到类的名称)。
初始化:它将告诉编译器为新创建的类型创建私有的后台字段和(只读的)属性。
通过传递参数构建⼀个匿名类型,并打印相关信息
private static void BiuldAnonymousType(string make, string color, int currSp)
{
// 使⽤传⼊参数构建匿名类型
var car = new { Make = make, Color = color, CurrSp = currSp };
// 获取属性数据
Console.WriteLine($"{car.Color} 的 {car.Make} 时速{car.CurrSp}");
// 匿名类型包含对System.Object中每个虚⽅法(virtual)的⾃定义实现
Console.WriteLine($"ToString={car.ToString()}");
}
调⽤:也可以使⽤硬编码构建匿名类型
public static void Show()
{
Console.WriteLine("fun with anonymous types");
// 注意匿名类型也可以使⽤硬编码创建
// 构建⼀个匿名对象表⽰汽车
var car = new { Make = "honda", Color = "blue", CurrSp = 180 };
// 输出颜⾊和车
Console.WriteLine($"我的车是{car.Color}{car.Make}");
// 调⽤辅助⽅法通过参数创建匿名类型
BiuldAnonymousType("baoma", "white", 220);
}
2.匿名类型的内部表⽰⽅式
所有的匿名类型都⾃动继承Object,所以我们可以在 car 对象上ToString,GetHashCode,Equals,我们尝试调⽤⼀下:private static void ReflectOverAnonymousType(object obj)
{
Console.WriteLine($"对象实例:{obj.GetType().Name}");
Console.WriteLine($"类型: {obj.GetType().Name} 基类: {obj.GetType().BaseType}");
Console.WriteLine($"toString():{obj.ToString()}");
Console.WriteLine($"getHashCode():{obj.GetHashCode()}");
}
调⽤以及结果:
public static void Show()
{
Console.WriteLine("fun with anonymous types");
// 构建⼀个匿名对象表⽰汽车
var car = new { Make = "honda", Color = "blue", CurrSp = 180 };
ReflectOverAnonymousType(car);
}
car对象的类型是:<>f__AnonymousType0`3(你的或许不同),匿名类型名称由编译器觉得,我们⽆从⼲涉,CIL代码。
3.⽅法 ToString()和 GetHashCode()的实现
1.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(", CurrSp = ");
builder.Append(this.<CurrSp>i_Field);
builder.Append("}");
return builder.ToString();
}
2.GetHashCode()
它使⽤每个匿名类型的变量计算出散列值作为System.Collections.Generic.EqualityComparer<T>的类型输⼊,仅当两个匿名类型有相同的属性并且被赋予了相同的值,才会产⽣相同的散列值。
4.匿名类型的相等语义
Equals()
private static void EqualityTest()
{
// 构建两个匿名类型,拥有相同的名称/值对
var oneCar = new { Make = "honda", Color = "blue", CurrSp = 180 };
var twoCar = new { Make = "honda", Color = "blue", CurrSp = 180 };
// 调⽤Equals
if (oneCar.Equals(twoCar))
{
Console.WriteLine("Equals“同⼀个匿名对象");
}
else
{
Console.WriteLine("Equals“不是同⼀个匿名对象");
}
// 使⽤ == 操作符
if (oneCar == twoCar)
{
Console.WriteLine("==“同⼀个匿名对象");
}
else
{
Console.WriteLine("==“不是同⼀个匿名对象");
}
// ⽐较对象类型
if (oneCar.GetType().Name == twoCar.GetType().Name)
{
Console.WriteLine("同⼀个类型");
}
else
{
Console.WriteLine("不同类型");
}
ReflectOverAnonymousType(oneCar);
ReflectOverAnonymousType(twoCar);
}
分析⼀下这样的结果:
1.Equals():编译器重写Equals()在判断对象相等时使⽤了基于值得语义(如:笔记两个对象的每⼀个数据成员的值)
2.==操作符:是因为匿名类型没有重载相等操作符(==,!=),所以==⽐较的是引⽤,⽽不是内容。
3.GetType():是因为如果我们同⼀程序集中声明两个相同的(属性相同)匿名类型,编译器只会⽣成⼀个匿名类型的定义。
5.包含匿名类型的匿名类型
var order = new
{
car = new { Make = "honda", Color = "blue", CurrSp = 180 },
price = 200000
};
ReflectOverAnonymousType(order);
总结:
其实,我们应该谨慎使⽤匿名类型,尤其在使⽤LINQ时,永远不要因为匿名类型的出现⽽放弃使⽤强类型的类或结构。
其实,匿名类型本⾝有许多限制:
你并没有控制匿名类型的名称
匿名类型继承System.Object
匿名类型的字段和属性总是只读的
匿名类型不⽀持事件,⾃定义⽅法,⾃定义操作符和⾃定义重写
匿名类型是隐式封闭的(implicit sealed)
匿名类型的实体创建只使⽤默认构造函数
如果,我们需要快速定义⼀个实体的形状,⽽不需要定义其功能时,可以使⽤匿名类型。
学⽆⽌境,望各位看官多多指教。