看看这个超级实用的一种类型——匿名类型

  既然说到匿名类型超级实用,得要找到场景来说服一下,如果大家玩过php,里面有一个万能的关联数组array,任你在关联数组array里面怎么写,都

可以用json_encode来生成json,非常非常的方便。

<?php
   //可以这么写
   $arr= array("name"=>"hxc","age"=20,"isMale"=>true);

   //也可以这么写
   $arrayName = array("list" =>array(
                                           array("name" => "john", "age" => "20","isMale" => true),
                                           array("name" => "mary", "age" => "24","isMale" => false),
                                           array("name" => "jackson", "age" => "30","isMale" => true)
                                        ),"totalCount"=>100);

   $json=json_encode($arr);

   echo $json;

?>

而在使用C#的时候,我们要向前台输出json的时候,都是要先定义一个实体,再给实体各种赋值,然后序列化成json的形式输出到前台,就比如下面这样:

 1     public class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var json = new Student() { Name = "john", Age = 25, IsMale = true };
 6
 7             JavaScriptSerializer js = new JavaScriptSerializer();
 8
 9             var r = js.Serialize(json);
10     }

自从.netframework 3.5中新增了匿名类型之后,一切都有了新的变化。

一:寻找场景

<1>  场景1:

有时候我们想向前台输出json,但是这个json是个非常简单的状态json,就像这样{"status":"1","message":"提交成功"},但是以往的做法我必须要自己

先定义一个状态类,再序列化它,就像下面这样。

 1     public class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var json = new Status() { status = "1", message = "提交成功" };
 6
 7             JavaScriptSerializer js = new JavaScriptSerializer();
 8
 9             var result = js.Serialize(json);
10
11             Console.WriteLine(result);
12
13             Console.Read();
14         }
15
16         public class Status
17         {
18             public string status { get; set; }
19
20             public string message { get; set; }
21         }
22     }

再看看我们使用匿名类型的话,会是怎样?

 1         static void Main(string[] args)
 2         {
 3             var json = new { status = "1", message = "提交成功" };
 4
 5             JavaScriptSerializer js = new JavaScriptSerializer();
 6
 7             var result = js.Serialize(json);
 8
 9             Console.WriteLine(result);
10
11             Console.Read();
12         }

从上下文的代码量来说,确实让我们少写了很多代码,也就提高了我们的开发效率,有了这个匿名类型之后,我们也可以像php的array一样,随心所欲的定义

简单或者复杂的结构,然后序列化为json。

<2> 场景2:

还有一个经常用到的场景就是,我们在获取列表数据的时候,经常是采用分页的形式,比如一页是20条数据,但是为了前端方便分页,后端必须要传递一

个totalcout参数,这样的话,前端才知道pagecount=Math.ceil(totalcount/pagesize),算出总页数,在传统的方法上,我们需要在底层的List上再包装

一个类,然后再在这个类中增加一个totalcount属性,就像下面这样。

 1     /// <summary>
 2     /// 集合包装类
 3     /// </summary>
 4     public class StudentPage
 5     {
 6         public List<Student> list { get; set; }
 7         public int total { get; set; }
 8     }
 9     /// <summary>
10     /// student实体类
11     /// </summary>
12     public class Student
13     {
14         public string Name { get; set; }
15
16         public int Age { get; set; }
17
18         public bool IsMale { get; set; }
19     }

有了匿名类型之后,我们再也不用这么写了,应该像下面这样。

 1     public class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var list = new List<Student>()
 6             {
 7                   new Student(){ Name="john", Age=25, IsMale=true},
 8                   new Student(){ Name="mary", Age=24, IsMale=false},
 9                   new Student(){ Name="jackson",Age=30,IsMale=true}
10             };
11
12             //核心点
13             var json = new { List = list, TotalCount = 20 };
14
15             JavaScriptSerializer js = new JavaScriptSerializer();
16
17             var result = js.Serialize(json);
18
19             Console.WriteLine(result);
20
21             Console.Read();
22         }
23     }
24
25     public class Student
26     {
27         public string Name { get; set; }
28
29         public int Age { get; set; }
30
31         public bool IsMale { get; set; }
32     }

看到这样的json是不是有一种很爽的感觉?是的,确实在我们开发中非常的实用,那么问题来了,这么实用东西,它的原理在哪里可以学得到?

二:基本原理

  既然想学,我们就剖析下它的IL代码,看看这个东西到底都做了些什么?为了方便理解,我就定义一个非常简单的匿名类。

1 var json = new { Name = "jackson", Age = 20 };

然后我们看看IL中到底都发生了什么?

不看IL还好,一看真是吓一跳,就一句话的事情,变成IL后就有这么多的玩意。。。而且类名取得也是非常奇葩,开头居然有<>这种尖括号,当

然这么写的原因很简单,就是避免我们定义的类名与自动生成的相冲突,再说编译器也不允许用<>开头的类名,虽然在CLR层面是允许的,好了,

我们继续往下面,从IL上我们还发现了

两个模板参数:<Age>j__TPar 和 <Name>j__TPar。

两个字段:<Age>i__Field 和<Name>i__Field。

两个属性方法:get_Name和get_Age,这里我们发现并没有set_Name和set_Age方法,也就说明该属性是个只读属性。

最后我们还发现匿名类型还重写了equals,gethashcode 和 toString 方法,这里我就只看下equals方法吧。

可以看到,当类型中有泛型参数的加入,IL代码就变得非常难看并且容易混淆,不过可以找到几个关键指令,在重写object的equals方法之后,

匿名类型中比较相等的方法是采用逐一字段比较的,这就跟值类型的比较方式很类似了,既然是逐一比较,那么下面的两个匿名对象应该是相等的。

这个在引用类型中是不可想象的。

不过有趣的是,这时候我们再来看看IL代码,发现并没有生成两个匿名类,而是json和json2公用一个匿名类,这个好处就是减少了IL的指令量,

可以说编译器还是非常智能的,能够将资源优化到最佳。

好了,大体原理就这样了,如果你够聪明,一定会找到适合它的项目场景的 ^_^。

时间: 2024-12-25 11:14:41

看看这个超级实用的一种类型——匿名类型的相关文章

C#超级实用的一种类型—匿名类型

顾名思义 匿名类型就是没有名字的类型.当一个新的匿名对象定义与前面已经存在的类型定义的内部变量类型相同时,编译器就会只生成一个类定义,而不是各一个.匿名类型对象中仍然可以再包含匿名对象. 在C#3.0中允许我们在程序中声明一个临时的类型来存储数据,例如: class Program { static void Main(string[] args) { //声明一个匿名对象,拥有 Name和Age 属性 var obj = new { Name = "Joey", Age = 25 }

C#超级有用的一种类型—匿名类型

顾名思义 匿名类型就是没有名字的类型.当一个新的匿名对象定义与前面已经存在的类型定义的内部变量类型同样时,编译器就会仅仅生成一个类定义,而不是各一个. 匿名类型对象中仍然能够再包括匿名对象. 在C#3.0中同意我们在程序中声明一个暂时的类型来存储数据,比如: class Program { static void Main(string[] args) { //声明一个匿名对象,拥有 Name和Age 属性 var obj = new { Name = "Joey", Age = 25

超级实用的一种类型——匿名类型

既然说到匿名范例超等适用,得要找到场景来压服一下,假如人人玩过php,外面有一个全能的联系关系数组array,任你在联系关系数组array外面怎样写,均可以或许用json_encode来天生json,异常异常的便利.http://www.top388.com/jianzhanjingyan/20160715103844.html 看到如许的json是不是有一种很爽的感到?是的,确其实咱们开辟中异常的适用,那末成绩来了,这么适用器械,它的道理在哪里可以或许学获得? 不看IL还好,一看真是吓一跳,就

C#编程(十六)----------匿名类型

匿名类型 var和new关键字一起使用,可以创建匿名类型. 匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型. 类型名由编译器生成,并且不能在源代码级使用. 每个属性的类型由编译器推断 public class BookAsGood { // 定义一组私有成员变量 private string m_name; private double m_price; // 为成员变量设置属性 public string Name { get { return 

C#匿名类型与VB匿名类型及其差异

一.C#中的匿名类型 匿名类型是C#3.0(framework3.5)中引入的一个新特性.匿名类型顾名思义,就是没有类型名称的一种对象,其直接从object继承 C#的匿名类型有两种方式定义: //1.直接声明成员,并初始化 Func<int, int> fun = x => x + 1; var ann1 = new { A = "Str", B = new Object(), C = fun //C#中可以使用委托,但是不能把一个拉姆达表达式直接赋值给成员,例如C

超级实用的 Java 工具类

超级实用的 Java 工具类 在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选取的5万个开源项目源码. 一. org.apache.commons.io.IOUtils closeQuietly:关闭一个IO流.socket.或者selector且不抛出异常,通常放在finally块 toString:转换IO流. Uri. byte[]为String copy:IO流数据复制

JVM实用参数(一)JVM类型以及编译器模式

JVM实用参数(一)JVM类型以及编译器模式 原文地址:https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-1-jvm-types-and-compiler-modes/ 译者:赵峰,iDestiny    校对:郭蕾 现在的JVM运行Java程序(和其它的兼容性语言)时在高效性和稳定性方面做的非常出色.自适应内存管理.垃圾收集.及时编译.动态类加载.锁优化——这里仅仅列举了某些场景下会发生的神奇的事情,但他们几乎不会直接与普

APICloud开发者进阶之路 | 超级实用技巧

金秋9月,脑海还是北京的"中非合作蓝"!今天按照惯例,柚子君还是要督促大家充充电的! 本周<30天,App开发从0到1>将要给大家分享第十章超级实用技巧,我们精选了其中的一个章节--地图模块的实用扩展:在地图上添加自定义按钮,一起来学习吧. 主要内容本章将向读者介绍一些开发中常用的功能和技巧 , 这些技巧涉及应用开发的方方面面. 示例 1 讲解了屏幕动态适配的方法,是开发 App 必须具备要掌握的技能之一:示例 2.示例 7.示例 9 -示例 11 具体讲解了一些常见的业务

HTML 4.01 规定了三种文档类型

HTML 4.01 规定了三种文档类型:Strict.Transitional 以及 Frameset. 严格的——该 DTD 包含所有 HTML 元素和属性,但不包括展示性的和弃用的元素(比如 font).不允许框架集(Framesets). <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 过渡的——该 DTD 包含所有