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

简介: 原文:看看这个超级实用的一种类型——匿名类型  既然说到匿名类型超级实用,得要找到场景来说服一下,如果大家玩过php,里面有一个万能的关联数组array,任你在关联数组array里面怎么写,都 可以用json_encode来生成json,非常非常的方便。
原文: 看看这个超级实用的一种类型——匿名类型

  既然说到匿名类型超级实用,得要找到场景来说服一下,如果大家玩过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的指令量,

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

 

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

 

目录
相关文章
|
编解码 openCL TensorFlow
RK3568开发笔记(一):瑞芯微RK3568芯片介绍,入手开发板的核心板介绍
RK3568开发笔记(一):瑞芯微RK3568芯片介绍,入手开发板的核心板介绍
RK3568开发笔记(一):瑞芯微RK3568芯片介绍,入手开发板的核心板介绍
|
SQL 监控 数据可视化
数据中台如何实现数据共享?用这个工具即可
DataAPI,通过双模式可视化配置生成与注册API,快速构建Oneservice数据服务,形成企业级的API市场和API服务管理平台,提高数据开放与共享效率
5646 0
|
人工智能 算法 数据可视化
使用低代码平台,让复杂的应用开发变得更轻松
低代码平台通过模块化设计和五大技术引擎,支持快速开发高效、灵活的业务应用,显著降低开发门槛。平台兼容多种数据库,提供丰富的插件生态和组件库,支持跨平台应用,帮助企业快速响应市场需求,优化系统性能和运营效率。
Nyx
|
Java
通义灵码提升项目效率
本文介绍了作者作为Java后端开发工程师使用通义灵码进行项目开发的体验。通过安装插件、初步体验(了解项目结构、项目优化、异常排查、代码生成)和使用@terminal注解,作者感受到了显著的开发效率提升。文中还分享了作者的心得体会,强调了快速熟悉项目代码和整体架构的重要性。
Nyx
331 4
|
监控 JavaScript 算法
深度剖析 Vue.js 响应式原理:从数据劫持到视图更新的全流程详解
本文深入解析Vue.js的响应式机制,从数据劫持到视图更新的全过程,详细讲解了其实现原理和运作流程。
|
前端开发 安全 开发者
【通义灵码实践】实现经典手机游戏推箱子
本文介绍了使用通义灵码辅助实现经典推箱子游戏的过程。首先,通过输入“用Python写一个推箱子游戏”,灵码生成了基本的终端版本代码,包括地图渲染、玩家移动和胜利检测等功能。然而,终端版本交互体验不佳。为了解决这一问题,再次输入“不要在终端上运行,希望可以在页面上运行”,灵码生成了基于Flask的后端代码和HTML前端代码,实现了网页版推箱子游戏。最终结果展示了游戏的完整实现,包括前后端交互和用户界面。总结中提到,该方法具有快速生成代码、代码质量高、易于扩展等优点,但也存在功能简单、样式和用户体验有限、错误处理不足等问题,适合快速原型开发和教学演示。
439 2
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
408 2
【异常】svn: E200009: Commit failed (details follow)/both sides of the move must be committed together的解决办法
svn: E200009: Commit failed (details follow)/both sides of the move must be committed together的解决办法
1044 0
|
网络安全 开发工具 git
服务器 ssh key 与 git 配置
程序员经常会说一句话: 面向 github 编程,github 对程序员的重要性可见一斑 虽然 git 可以工作在 ssh 与 https 两种协议上,但为了安全性,更多时候会选择 ssh。 如果采用 https,则每次 git push 都需要验证身份 所以此篇文章的主要内容是: ssh keygen: 生成非对称加密中的 public-key 与 private-key,并把 publik-key 扔到 github 上。
3012 0
|
人工智能 弹性计算 数据安全/隐私保护
如何在阿里云快速启动Stable Diffusion轻松玩转AI绘画
本文介绍如何如何在阿里云快速启动Stable Diffusion服务开启AI绘画
如何在阿里云快速启动Stable Diffusion轻松玩转AI绘画