C#是一门静态类型的语言,但是在C#4.0时微软引入了动态类型的概念。

dynamic

关键字dynamic用来定义动态对象,我们来看一下动态类型的一些特性。

调用不同类的相同方法

我们有两个或多个不相关的类,然后运行时需要可以调用到相同名称的方法,如下:

 1 using System;
 2
 3 namespace Study
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             dynamic obj = GetObject(0);
10             Console.WriteLine(obj.Talk());
11
12             Console.Read();
13         }
14
15         private static Object GetObject(int type)
16         {
17             switch (type)
18             {
19                 case 1:
20                     return new Dog();
21             }
22             return new Robot();
23         }
24     }
25
26     public class Dog
27     {
28         public string Talk()
29         {
30             return "Wang Wang!";
31         }
32     }
33
34     public class Robot
35     {
36         public string Talk()
37         {
38             return "I`m a Robot!";
39         }
40     }
41 }

我们的两个类没有继承也没有应用相同的接口,但是可以调用到相同的方法,使用GetObject(1)可以得到想要的结果。

这就是动态类型,在编译时不会对方法等进行判断,而是在运行时才进行处理,如果调用到不存在的方法才会报错。

C#编译器允许你通过dynamic对象调用任何方法,即使这个方法根本不存在,编译器也不会在编译的时候报编译错误。只有在运行的时候,它才会检查这个对象的实际类型,并检查在它上面Talk()是什么意思。动态类型将使得C#可以以更加统一而便利的形式表示下列对象:

  • 来自动态编程语言——如Python或Ruby——的对象;
  • 通过IDispatch访问的COM对象;
  • 通过反射访问的一般.NET类型;
  • 结构发生过变化的对象——如HTML DOM对象;

当我们得到一个动态类型的对象时,不管它是来自COM还是IronPython、HTML DOM还是反射,只需要对其进行操作即可,动态语言运行时(DLR)会帮我们指出针对特定的对象以及这些操作的具体意义。这将给我们的开发带来极大的灵活性,并且能够极大程度上地精简我们的代码。

动态类型使用注意

  1. 不能调用扩展方法;
  2. 委托与动态类型不能进行隐式转换;
  3. 不能调用构造函数和静态方法;
  4. 类不能继承dynamic、泛型参数不能使用dynamic和接口实现也不能使用dynamic;

实现动态行为

实现动态行为有3种方法,分别可以用在不同的场合。

使用ExpandoObject类

直接使用ExpandoObject类来实现动态行为,代码如下:

 1 using System;
 2 using System.Dynamic;
 3
 4 namespace Study
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             dynamic obj = new ExpandoObject();
11             //添加属性
12             obj.name = "Li Lei";
13             obj.age = 20;
14             //添加方法
15             obj.Add = (Func<int, int, int>) ((a, b) => a + b);
16
17             Console.WriteLine("Name: " + obj.name);
18             Console.WriteLine("Age: " + obj.age);
19             Console.WriteLine("Add: " + obj.Add(100, 123));
20
21             Console.Read();
22         }
23     }
24 }

输出如下:

1 Name: Li Lei
2 Age: 20
3 Add: 223

继承DynamicObject类

通过继承DynamicObject类也可以实现动态效果,示例如下:

 1 using System;
 2 using System.Dynamic;
 3
 4 namespace Study
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             dynamic obj = new MyClass();
11             obj.name = "Li Lei";
12             obj.age = 20;
13             obj.CallFunc();
14
15             Console.Read();
16         }
17     }
18
19     public class MyClass : DynamicObject
20     {
21         public override bool TrySetMember(SetMemberBinder binder, object value)
22         {
23             Console.WriteLine("设置" + binder.Name + "为" + value);
24             return true;
25         }
26
27         public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
28         {
29             Console.WriteLine("调用" + binder.Name + "方法");
30             result = null;
31             return true;
32         }
33     }
34 }

输出如下:

1 设置name为Li Lei
2 设置age为20
3 调用CallFunc方法

实现IDynamicMetaObjectProvider接口

如果已经继承了其它的类,则可以通过实现IDynamicMetaObjectProvider接口来实现动态行为,例子如下:

 1 using System;
 2 using System.Dynamic;
 3 using System.Linq.Expressions;
 4
 5 namespace Study
 6 {
 7     class Program
 8     {
 9         static void Main(string[] args)
10         {
11             dynamic obj = new MyClass();
12             obj.CallFunc();
13
14             Console.Read();
15         }
16     }
17
18     public class MyClass : IDynamicMetaObjectProvider
19     {
20         public DynamicMetaObject GetMetaObject(Expression parameter)
21         {
22             Console.WriteLine("获取元数据");
23             return new MetaDynamic(parameter, this);
24         }
25     }
26
27     public class MetaDynamic : DynamicMetaObject
28     {
29         public MetaDynamic(Expression expression, object value) : base(expression, BindingRestrictions.Empty, value)
30         {
31         }
32
33         public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
34         {
35             MyClass target = base.Value as MyClass;
36             Expression self = Expression.Convert(base.Expression, typeof (MyClass));
37             var restrictions = BindingRestrictions.GetInstanceRestriction(self, target);
38             Console.WriteLine("调用" + binder.Name + "方法");
39             return new DynamicMetaObject(self, restrictions);
40         }
41     }
42 }

输出如下:

1 获取元数据
2 调用CallFunc方法

转载于:https://www.cnblogs.com/hammerc/p/4614313.html

C#学习笔记(十一):动态类型相关推荐

  1. WebGL three.js学习笔记 6种类型的纹理介绍及应用

    WebGL three.js学习笔记 6种类型的纹理介绍及应用 本文所使用到的demo演示: 高光贴图Demo演示 反光效果Demo演示(因为是加载的模型,所以速度会慢) (一)普通纹理 计算机图形学 ...

  2. Go圣经-学习笔记之复合类型(二)

    2019独角兽企业重金招聘Python工程师标准>>> 上一篇 Go圣经-学习笔记之复合类型 下一篇 Go圣经-学习笔记之复合数据结构(三) map介绍和简单使用 map是一种无序的 ...

  3. JavaWeb学习笔记(动态SQL)

    JavaWeb学习笔记(动态SQL) 动态SQL中的元素 < if>元素 < choose>.< when>.< otherwise>元素 < w ...

  4. xcode 学习笔记2:动态添加view

    xcode 学习笔记2:动态添加view 2011-07-06 16:48:39|  分类: 计算机学习|字号 订阅 前面说的都是用的Interface Builder来编辑.xib文件来给窗口添加各 ...

  5. Apache Nutch 1.3 学习笔记十一(页面评分机制 OPIC)

    1. Nutch 1.3 的页面评分机制 Nutch1.3目前默认还是使用OPIC作为其网页分数算法,但其之后,已经引入了PageRank-like算法,以弥补OPIC算法的不足,目前OPIC算法还是 ...

  6. 吴恩达《机器学习》学习笔记十一——应用机器学习的建议

    吴恩达<机器学习>学习笔记十一--应用机器学习的建议 一.训练完模型后下一步要做什么 二.评估算法与模型选择 1.训练集与测试集 2.训练/测试步骤 3.模型选择 4.数据集新的划分--验 ...

  7. 吴恩达《机器学习》学习笔记十一——神经网络代码

    吴恩达<机器学习>学习笔记十一--神经网络代码 数据准备 神经网络结构与代价函数· 初始化设置 反向传播算法 训练网络与验证 课程链接:https://www.bilibili.com/v ...

  8. MyBatis:学习笔记(4)——动态SQL

    MyBatis:学习笔记(4)--动态SQL 转载于:https://www.cnblogs.com/MrSaver/p/7453949.html

  9. ROS学习笔记十一:ROS中数据的记录与重放

    ROS学习笔记十一:ROS中数据的记录与重放 本节主要介绍如何记录一个正在运行的ROS系统中的数据,然后在一个运行的系统中根据记录文件重新产生和记录时类似的运动情况.本例子还是以小海龟例程为例. 记录 ...

  10. Apache Nutch 1.3 学习笔记十一(页面评分机制 LinkRank 介绍)

    下面是Google翻译的http://wiki.apache.org/nutch/NewScoring内容,是关于Nutch 新的链接分数算法的说明,有点类似于Google的PageRank,这里有其 ...

最新文章

  1. python3.6 asyncio paramiko_Python开发【第六篇】:模块
  2. linux内核链表分析
  3. 路由网址这是mvc时代系列之三:网络路由与ASP.NET MVC生命周期(上)路由网址
  4. windows下安装及配置 golang 的Web框架Beego环境
  5. 作为前端开发,如何高效学习 TypeScript
  6. php查询车位系统代码,php车辆违章查询数据示例
  7. Flex学习笔记(2)——使用ActionScript脚本
  8. vscode 注释插件
  9. 【Kafka】kafka replication factor : 3 larger than avaiable brokers:2
  10. Extjs数据展现原理
  11. [技术博客]使用wx.downloadfile将图片下载到本地临时存储
  12. 三星s9 港版android 9.0,国行三星Galaxy S9/S9+更新One UI正式版,基于安卓9.0
  13. linux网络对时命令
  14. 除了专业技能,Web前端工程师需要具备哪些基本素质?
  15. C语言中括号的用法[]
  16. 解决 pq: SSL is not enabled on the server
  17. 【51单片机】OOK无线通讯在无线门磁报警中的应用
  18. 【leetcode】2248. 多个数组求交集(js实现)
  19. Linux下SD卡开发笔记(一)-SD 相关基础概念
  20. 基于Arduino的无接触式智能门锁(RFID和蓝牙开锁)

热门文章

  1. 【51nod - 1073】约瑟夫环问题模板
  2. 从零开始学视觉Transformer(1):Hello Vision Transformer
  3. 2.2)深度学习笔记:优化算法
  4. java中的values函数_巧用valueat函数(快逸免费版)
  5. vb外部调用autocad_AutoCAD教程之图块的各种相关操作和概念
  6. java生命小游戏_Java修炼——飞机生存小游戏
  7. 三相同步电机怎么接线图_智能电表怎么接线 单相 三相电表接线图大全
  8. * 完成随机点名案例;学生姓名都提前写在文件中;:每次敲回车,随机显示一个学生姓名,每人最多显示一次,所有人都显示完了就结束程序;
  9. Arrays对数组,二分查找,冒泡排序
  10. e4a服务器文件,e4a链接网站服务器