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


    既然说到匿名类型超级有用,得要找到场景来说服一下。假设大家玩过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是个很easy的状态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代码,看看这个东西究竟都做了些什么?为了方便理解,我就定义一个很easy的匿名类。

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

     

    然后我们看看IL中究竟都发生了什么?

     

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

    然这么写的原因很easy,就是避免我们定义的类名与自己主动生成的相冲突,再说编译器也不同意用<>开头的类名,尽管在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代码就变得很难看并且easy混淆。只是能够找到几个关键指令,在重写object的equals方法之后,

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

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

     

    只是有趣的是,这时候我们再来看看IL代码,发现并没有生成两个匿名类。而是json和json2公用一个匿名类,这个优点就是降低了IL的指令量,

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

     

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

  • 相关阅读:
    MySQL锁之一:锁详解
    eclipse maven plugin 插件 安装 和 配置
    火星坐标系统
    使用Spring MVC统一异常处理实战
    websocket之二:WebSocket编程入门
    spring mvc 异常统一处理方式
    Android面向HTTP协议发送post请求
    用JAX-WS在Tomcat中公布WebService
    css3 -&gt; 多栏布局
    NSLayoutConstraint-代码实现自己主动布局的函数使用方法说明
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/8426574.html
Copyright © 2020-2023  润新知