C# 的 dynamic 关键字可以是C#可以像 javascript 这种弱类型语言一样具有随时可以添加属性的能力。C# 是一种强类型语言,dynamic 要摆脱类型的限制,自然是有代价的。这里不讨论CPU做了多少额外的工作使得 C# 具有了超脱其天性的能力。然而这种能力会简化我们的编程。在项目开发中给我带来的实实在在的好处就是减少创建模型类。

分享一下 dynamic 应用

在做 web 项目时,有时候页面上的某个角落要显示一些简单的信息,或者一些下拉框里的信息等等。这些信息的信息量小,用的地方少。为了获取这些信息专门定义一个 Class 有点不值得,而且增加了我们模型类的数量,看着那么多模型类就烦。 dynamic 关键词可以很好的解决这个问题。

 代码如下:

 1         /// <summary>
 2         /// 返回动态类型的数据。
 3         /// </summary>
 4         /// <returns></returns>
 5         private dynamic DynamicInfo()
 6         {
 7             dynamic item = null;
 8             List<ExpandoObject> li = new List<ExpandoObject>();
 9             for (var i = 65; i < 91; i++)
10             {
11                 item = new ExpandoObject();
12                 item.数字 = i;//为动态类型添加信息
13                 item.字母 = string.Format("{0}", (Char)i);//为动态类型添加信息
14                 li.Add(item);
15             }
16             return li;
17         }

怎么把这些动态信息返回到客户端呢?当然是序列化成json格式,通过 jQuery 的 ajax 功能很容易获取到。下面是mvc4里的实现:

1         public JsonResult GetDynamicInfo()
2         {
3             return Json(DynamicInfo(), JsonRequestBehavior.AllowGet);
4         }

客户端获取服务器端数据,并将数据以表格的形式显示的在客户端:

 1         $.getJSON("/Home/GetDynamicInfo", function (data) {
 2             if (data && data.length > 0) {
 3                 var table = document.createElement("table"), tr, td, text;
 4                 tr = document.createElement("tr");
 5                 table.appendChild(tr);
 6                 for (var b = 0; b < data[0].length; b++) {
 7                     td = document.createElement("td");
 8                     text = document.createTextNode(data[0][b].Key);
 9                     td.appendChild(text);
10                     tr.appendChild(td);
11                 }
12                 for (var a = 0; a < data.length; a++) {
13                     tr = document.createElement("tr");
14                     table.appendChild(tr);
15                     for (var b = 0; b < data[a].length; b++) {
16                         td = document.createElement("td");
17                         text = document.createTextNode(data[a][b].Value);
18                         td.appendChild(text);
19                         tr.appendChild(td);
20                     }
21                 }
22                 document.body.appendChild(table);
23             }
24         });

显示效果如下,当然有点简陋:

上面分享了从服务器端到客户端的整个过程,可以看到利用动态类型,我们并没有建立一个具有数字,字母两个字段的模型类。

关于 dynamic

dynamic 类型定义的代码,在编译期间不会进行类型检查,编译器假定给 dynamic 类型定义的对象的任何操作都是正确的。 dynamic 与 var 这两个关键词是不一样的。var 关键词定义的对象只是延迟确定其类型,类型一旦确定,就不能再改变了。而 dynamic 定义的类型在运行期间可以多次被改变。为什么呢,很简单,因为 dynamic 类型的对象是在运行期间根据程序的静态代码信息确定的,也就是在编写代码时定义了多少种类型,那么运行期间就可以确定出对应的类型。例如:

1 dynamic d = 0;
2 d = "change to a string.";
3 d = 'a';

运行期间,就可以计算出对象 d 依次是 int, string, char.

dynamic 为我们的编程带来方便的同时,也是以牺牲了一部分性能为代价的。查看 dynamic 类型的代码生成的 IL,会发现编译器做了很多的工作。

查看第一部分分享应用的代码,会发现用了一个 ExpandoObject 类。这个类微软定义的应用动态类型的辅助类,是一个密封类,继承自 DynamicObject。 当然在使用动态类型时,也可以直接使用 DynamicObject,但是要做很多的工作去实现类似 ExpandoObject 实现的工作。既然微软已经有现成的,那么就用现成的吧。