C#匿名类型(Anonymous Type)学习日记
2015-08-09 15:25
399 查看
当我们不要定义复杂的方法,事件,构造函数这样复杂的类的时候,可以动态的生成一个自定义的数据类型 --> 匿名类型。
1.定义匿名类型
定义一个匿名类型时,需要用到 var 关键字和对象初始化语法。
var : 编译器会在编译时自动生成新类定义(我们无法在C#代码中看到类的名称)。
初始化:它将告诉编译器为新创建的类型创建私有的后台字段和(只读的)属性。
通过传递参数构建一个匿名类型,并打印相关信息
调用:也可以使用硬编码构建匿名类型
2.匿名类型的内部表示方式
所有的匿名类型都自动继承Object,所以我们可以在 car 对象上ToString,GetHashCode,Equals,我们尝试调用一下:
调用以及结果:
car对象的类型是:<>f__AnonymousType0`3(你的或许不同),匿名类型名称由编译器觉得,我们无从干涉,CIL代码。
3.方法 ToString() 和 GetHashCode() 的实现
1.ToString()
2.GetHashCode()
它使用每个匿名类型的变量计算出散列值作为System.Collections.Generic.EqualityComparer<T>的类型输入,仅当两个匿名类型有相同的属性并且被赋予了相同的值,才会产生相同的散列值。
4.匿名类型的相等语义
Equals()
分析一下这样的结果:
1.Equals():编译器重写Equals()在判断对象相等时使用了基于值得语义(如:笔记两个对象的每一个数据成员的值)
2.==操作符:是因为匿名类型没有重载 相等操作符(==,!=),所以==比较的是引用,而不是内容。
3.GetType():是因为如果我们同一程序集中声明两个相同的(属性相同)匿名类型,编译器只会生成一个匿名类型的定义。
5.包含匿名类型的匿名类型
总结:
其实,我们应该谨慎使用匿名类型,尤其在使用LINQ时,永远不要因为匿名类型的出现而放弃使用强类型的类或结构。
其实,匿名类型本身有许多限制:
你并没有控制匿名类型的名称
匿名类型继承System.Object
匿名类型的字段和属性总是只读的
匿名类型不支持事件,自定义方法,自定义操作符和自定义重写
匿名类型是隐式封闭的(implicit sealed)
匿名类型的实体创建只使用默认构造函数
如果,我们需要快速定义一个实体的形状,而不需要定义其功能时,可以使用匿名类型。
学无止境,望各位看官多多指教。
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)
匿名类型的实体创建只使用默认构造函数
如果,我们需要快速定义一个实体的形状,而不需要定义其功能时,可以使用匿名类型。
学无止境,望各位看官多多指教。
相关文章推荐
- 国内大型的内部 C# 编程规范
- C#调用外部EXE-LibSVM为例
- 使用C# 和Consul进行分布式系统协调
- C#.net中如何操作XML
- 用C#生成KML路径文件(下篇)
- 使用C#详解常用排序算法(二):插入排序(Insert Sort)
- 使用C#详解常用排序算法(一):概述
- C#中得到两个数百分比
- 匹夫细说C#:庖丁解牛聊委托,那些编译器藏的和U3D给的
- C#中的集合有几种?
- Visual C#2010学习笔记三之return返回值的使用
- C#高级编程八十天----异常类
- 【常用】C#万年历代码
- C# 入门篇之listview用法
- C#-WinForm登录窗体实现记住密码的功能(仿QQ实现)
- C# 结构体
- c#中的事件
- C# 枚举
- 利用VS C# 实现串口控制视频的播放 use VLC
- 用C#生成KML路径文件(上篇)