架构师_程序员

查看: 86|回复: 0

[资料] C# 匿名类型(Anonymous Type)学习日记

[复制链接]
发表于 2020-10-16 17:41:04 | 显示全部楼层
当我们不要定义复杂的方法,事件,构造函数这样复杂的类的时候,可以动态的生成一个自定义的数据类型 --> 匿名类型。

1.定义匿名类型

定义一个匿名类型时,需要用到 var 关键字和对象初始化语法。

var : 编译器会在编译时自动生成新类定义(我们无法在C#代码中看到类的名称)。

初始化:它将告诉编译器为新创建的类型创建私有的后台字段和(只读的)属性。

通过传递参数构建一个匿名类型,并打印相关信息

  1. private static void BiuldAnonymousType(string make, string color, int currSp)
  2. {
  3.     // 使用传入参数构建匿名类型
  4.     var car = new { Make = make, Color = color, CurrSp = currSp };

  5.     // 获取属性数据
  6.     Console.WriteLine($"{car.Color} 的 {car.Make} 时速{car.CurrSp}");

  7.     // 匿名类型包含对System.Object中每个虚方法(virtual)的自定义实现
  8.     Console.WriteLine($"ToString={car.ToString()}");
  9. }
复制代码


调用:也可以使用硬编码构建匿名类型

  1. public static void Show()
  2. {
  3.     Console.WriteLine("fun with anonymous types");

  4.     // 注意 匿名类型也可以使用硬编码创建
  5.     // 构建一个匿名对象表示汽车
  6.     var car = new { Make = "honda", Color = "blue", CurrSp = 180 };

  7.     // 输出颜色和车
  8.     Console.WriteLine($"我的车是{car.Color}{car.Make}");

  9.     // 调用辅助方法通过参数创建匿名类型
  10.     BiuldAnonymousType("baoma", "white", 220);
  11. }
复制代码


2.匿名类型的内部表示方式

所有的匿名类型都自动继承Object,所以我们可以在 car 对象上ToString,GetHashCode,Equals,我们尝试调用一下:

  1. private static void ReflectOverAnonymousType(object obj)
  2. {
  3.     Console.WriteLine($"对象实例:{obj.GetType().Name}");
  4.     Console.WriteLine($"类型: {obj.GetType().Name} 基类: {obj.GetType().BaseType}");
  5.     Console.WriteLine($"toString():{obj.ToString()}");
  6.     Console.WriteLine($"getHashCode():{obj.GetHashCode()}");
  7. }
复制代码


调用以及结果:

  1. public static void Show()
  2. {
  3.     Console.WriteLine("fun with anonymous types");

  4.     // 构建一个匿名对象表示汽车
  5.     var car = new { Make = "honda", Color = "blue", CurrSp = 180 };

  6.     ReflectOverAnonymousType(car);
  7. }
复制代码


4230b158-035b-4b22-b597-0b668de539e5.png

6078a21b-1c5f-4d36-b2f5-3f3839f8c1dd.png

car对象的类型是:<>f__AnonymousType03(你的或许不同),匿名类型名称由编译器觉得,我们无从干涉,CIL代码。

3.方法 ToString() 和 GetHashCode() 的实现

1.ToString()

  1. public override string ToString()
  2. {
  3.     StringBuilder builder = new StringBuilder();
  4.     builder.Append("{ Color = ");
  5.     builder.Append(this.<Color>i_Field);
  6.     builder.Append(", Make = ");
  7.     builder.Append(this.<Make>i_Field);
  8.     builder.Append(", CurrSp = ");
  9.     builder.Append(this.<CurrSp>i_Field);
  10.     builder.Append("}");
  11.     return builder.ToString();
  12. }
复制代码


2.GetHashCode()

它使用每个匿名类型的变量计算出散列值作为System.Collections.Generic.EqualityComparer<T>的类型输入,仅当两个匿名类型有相同的属性并且被赋予了相同的值,才会产生相同的散列值。

4.匿名类型的相等语义

Equals()

  1. private static void EqualityTest()
  2. {
  3.     // 构建两个匿名类型,拥有相同的名称/值对
  4.     var oneCar = new { Make = "honda", Color = "blue", CurrSp = 180 };
  5.     var twoCar = new { Make = "honda", Color = "blue", CurrSp = 180 };

  6.     // 调用Equals
  7.     if (oneCar.Equals(twoCar))
  8.     {
  9.         Console.WriteLine("Equals“同一个匿名对象");
  10.     }
  11.     else
  12.     {
  13.         Console.WriteLine("Equals“不是 同一个匿名对象");
  14.     }

  15.     // 使用 == 操作符
  16.     if (oneCar == twoCar)
  17.     {
  18.         Console.WriteLine("==“同一个匿名对象");
  19.     }
  20.     else
  21.     {
  22.         Console.WriteLine("==“不是 同一个匿名对象");
  23.     }

  24.     // 比较对象类型
  25.     if (oneCar.GetType().Name == twoCar.GetType().Name)
  26.     {
  27.         Console.WriteLine("同一个类型");
  28.     }
  29.     else
  30.     {
  31.         Console.WriteLine("不同类型");
  32.     }

  33.     ReflectOverAnonymousType(oneCar);
  34.     ReflectOverAnonymousType(twoCar);
  35. }
复制代码


c0f6d288-cd12-45f7-9b06-0be928280ffe.png

分析一下这样的结果:

1.Equals():编译器重写Equals()在判断对象相等时使用了基于值得语义(如:笔记两个对象的每一个数据成员的值)

2.== 操作符:是因为匿名类型没有重载相等操作符(== ,!=),所以==比较的是引用,而不是内容。

3.GetType():是因为如果我们同一程序集中声明两个相同的(属性相同)匿名类型,编译器只会生成一个匿名类型的定义。

5.包含匿名类型的匿名类型

  1. var order = new
  2. {
  3.     car = new { Make = "honda", Color = "blue", CurrSp = 180 },
  4.     price = 200000
  5. };

  6. ReflectOverAnonymousType(order);
复制代码


总结:

其实,我们应该谨慎使用匿名类型,尤其在使用LINQ时,永远不要因为匿名类型的出现而放弃使用强类型的类或结构。

其实,匿名类型本身有许多限制:

  • 你并没有控制匿名类型的名称
  • 匿名类型继承System.Object
  • 匿名类型的字段和属性总是只读的
  • 匿名类型不支持事件,自定义方法,自定义操作符和自定义重写
  • 匿名类型是隐式封闭的(implicit sealed)
  • 匿名类型的实体创建只使用默认构造函数


如果,我们需要快速定义一个实体的形状,而不需要定义其功能时,可以使用匿名类型。




上一篇:sql server 数据导出为insert script
下一篇:.net/c# 反射非匿名函数 &lt;&gt;f__AnonymousType0 方法
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2020-10-28 22:30

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表