博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#学习笔记(十一):动态类型
阅读量:7071 次
发布时间:2019-06-28

本文共 4542 字,大约阅读时间需要 15 分钟。

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 Dog27     {28         public string Talk()29         {30             return "Wang Wang!";31         }32     }33 34     public class Robot35     {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
) ((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 Lei2 Age: 203 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 : DynamicObject20     {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 Lei2 设置age为203 调用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 : IDynamicMetaObjectProvider19     {20         public DynamicMetaObject GetMetaObject(Expression parameter)21         {22             Console.WriteLine("获取元数据");23             return new MetaDynamic(parameter, this);24         }25     }26 27     public class MetaDynamic : DynamicMetaObject28     {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方法

 

转载地址:http://zhzml.baihongyu.com/

你可能感兴趣的文章
POJ 1321 棋盘问题(DFS板子题,简单搜索练习)
查看>>
POJ 3155 Hard Life(最大密度子图)
查看>>
剑英的区块链学习手记(二)
查看>>
.Net接口调试与案例
查看>>
SQL Server 中BIT类型字段增删查改那点事
查看>>
【Java集合源代码剖析】TreeMap源代码剖析
查看>>
【算法】 算法和数据结构绪论
查看>>
LeetCode OJ 之 Ugly Number II (丑数-二)
查看>>
(一)Thymeleaf用法——Thymeleaf简介
查看>>
【Python】 命名空间与LEGB规则
查看>>
巴斯卡三角形
查看>>
产品和团队
查看>>
mysql取差集、交集、并集
查看>>
Tex: The top-level auxiliary file: *.aux I couldn't open style file IEEEtran.bst 解决方法
查看>>
HDU 3080 The plan of city rebuild(prim和kruskal)
查看>>
三层架构—简析
查看>>
利用linux shell自己主动顶贴
查看>>
[转]MVC Razor模板引擎 @RenderBody、@RenderPage、@RenderSection及Html.RenderPartial、Html.RenderAction...
查看>>
bzoj 1860: [Zjoi2006]Mahjong麻将 题解
查看>>
第21章 RTX 低功耗之睡眠模式
查看>>