编写高质量C#代码学习笔记(5)
来源:互联网 发布:linux基础教程 编辑:程序博客网 时间:2024/05/22 05:21
使用dynamic来简化反射实现
- dynamic dynamicObject = GetDynamicObject();
- Console.WriteLine(dynamicObject.Name);
- Console.WriteLine(dynamicObject.SampleMethod());
当然,如果运行时dynamicObject不包含指定的这些特性(如上文中带返回值的方法SampleMethod),运行时程序会抛出一个RuntimeBinderException异常:
“System.Dynamic.ExpandoObject”未包含“SampleMethod”的定义。
注意 有人会将var这个关键字与dynamic进行比较。实际上,var和dynamic完全是两个概念,根本不应该放在一起比较。var实际上是编译期抛给我们的“语法糖”,一旦被编译,编译期会自动匹配var 变量的实际类型,并用实际类型来替换该变量的声明,这看上去就好像我们在编码的时候是用实际类型进行声明的。而dynamic被编译后,实际是一个object类型,只不过编译器会对dynamic类型进行特殊处理,让它在编译期间不进行任何的类型检查,而是将类型检查放到了运行期。
这从Visual Studio的编辑器窗口就能看出来。以var声明的变量支持“智能感知”,因为Visual Studio能推断出var类型的实际类型;而以dynamic声明的变量却不支持“智能感知”,因为编译器对其运行期的类型一无所知。对dynamic变量使用“智能感知”,会提示“此操作将在运行时解析”。
利用dynamic的这个特性,可以简化C#中的反射语法。在dynamic出现之前,假设存在类,代码如下所示:
public class DynamicSample { public string Name { get; set; } public int Add(int a, int b) { return a + b; } }调用方代码如下所示:
//使用反射 DynamicSample dynamicSample = new DynamicSample(); var addMethod = typeof(DynamicSample).GetMethod("Add"); int re = (int)addMethod.Invoke(dynamicSample, new object[] { 1, 2 }); Console.WriteLine(re.ToString()); //使用dynamic简化反射【在使用dynamic后,代码看上去更简洁了,并且在可控的范围内减少了一次拆箱的机会】 dynamic dynamicSample2 = new DynamicSample(); int re2 = dynamicSample2.Add(1, 2); Console.WriteLine(re2.ToString());我们可能会对这样的简化不以为然,毕竟代码看起来并没有减少多少,但是,如果考虑到效率兼优美两个特性,那么dynamic的优势就显现出来了。如果对上面的代码执行1000000次,如下所示:
//下面是反射和dynamic的性能测试 int times = 1000000; DynamicSample reflectSample = new DynamicSample(); var addMethod = typeof(DynamicSample).GetMethod("Add"); Stopwatch watch1 = Stopwatch.StartNew(); for (var i = 0; i < times; i++) { addMethod.Invoke(reflectSample, new object[] { 1, 2 }); } Console.WriteLine(string.Format("反射耗时:{0} 毫秒", watch1.ElapsedMilliseconds)); dynamic dynamicSample = new DynamicSample(); Stopwatch watch2 = Stopwatch.StartNew(); for (int i = 0; i < times; i++) { dynamicSample.Add(1, 2); } Console.WriteLine(string.Format("dynamic耗时:{0} 毫秒", watch2.ElapsedMilliseconds)); /* * 输出结果是: * 反射耗时:1358 毫秒 * dynamic耗时:66 毫秒 * 请按任意键继续. . . */可以看到,没有优化的反射实现,上面这个循环上的执行效率大大低于dynamic实现的效果。如果对反射实现进行优化,代码如下所示:
//优化后的反射 DynamicSample reflectSampleBetter = new DynamicSample(); var addMethod2 = typeof(DynamicSample).GetMethod("Add"); var delg = (Func<DynamicSample, int, int, int>)Delegate.CreateDelegate(typeof( Func<DynamicSample, int, int, int>), addMethod2); Stopwatch watch3 = Stopwatch.StartNew(); for (var i = 0; i < times; i++) { delg(reflectSampleBetter, 1, 2); } Console.WriteLine(string.Format("优化的反射耗时:{0} 毫秒", watch3.ElapsedMilliseconds)); /*输出结果是: * 反射耗时:1414 毫秒 * dynamic耗时:67 毫秒 * 优化的反射耗时:9 毫秒 * 请按任意键继续. . . */
可以看到,优化后的反射实现,其效率和dynamic在一个数量级上。可是它带来了效率,却牺牲了代码的整洁度,这种实现在我看来是得不偿失的。所以,现在有了dynamic类型,建议大家:
始终使用dynamic来简化反射实现。
- 编写高质量C#代码学习笔记(5)
- 编写高质量C#代码学习笔记(1)
- 编写高质量C#代码学习笔记(2)
- 编写高质量C#代码学习笔记(3)
- 编写高质量C#代码学习笔记(4)
- 编写高质量C#代码学习笔记(6)
- 编写高质量C#代码(5)
- 编写高质量代码、学习笔记——CSS篇
- 编写高质量代码、学习笔记——Javascript篇
- 编写高质量代码(5)
- 编写高质量代码:改善Java程序的151个建议-学习笔记(5-8章)
- 《构建高质量的C#代码》学习笔记
- 编写高质量代码——笔记
- 编写高质量代码
- 编写高质量代码
- 更锋利的C#代码--编写高质量C#程序
- 《编写高质量代码改善C#程序的157个建议》学习
- 《代码大全》学习笔记(5):高质量子程序特点
- android下PDF格式的地图数据的显示------超大PDF页面显示策略(二)
- 在指定目录下创建一个txt文件
- 标签云
- poj 1747 -- Expression(递归)
- HDU2050折线分割平面
- 编写高质量C#代码学习笔记(5)
- 留言板需求
- 未来计划
- php语法复习
- mysql数据库存储过程之事务
- 纪念乔布斯
- 使用repeater控件进行分页代码
- 项目管理本质论 .
- Automatic Reference Counting(ARC)特性学习(iOS5新特性学习之五)