C#学习笔记(十一):动态类型

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++面试试题

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** from&#xff1a;http://blog.csdn.net/eddy_0825/article/details/1875597 1 …

《FPGA全程进阶---实战演练》第二十一章 电源常用类型:LDO和 DCDC

高速电路中的电源设计 高速电路中的电源设计大概分为两种&#xff0c;一种是集总式架构&#xff0c;一种是分布式架构。集总式架构就是由一个电源输入&#xff0c;然后生成多种所需要的电压。如图1所示。这种架构会增加多个DC/DC模块&#xff0c;这样成本不可控&#xff0c;PCB…

自定义View控件(2—手写实例代码)

1、 步骤: 1.自定义一个类继承于UIView 2.在initWithFrame方法中添加子控件 3.在layoutSubviews中设置子控件的位置 4.提供一个属性保存外界传入的数据(模型对象), 重写setter方法设置子控件的数据 - 类工厂方法(便利构造器) 按照苹果的风格和规范, 一般情况一个用于创建对…

pojo java_Java——POJO总结

一&#xff1a;什么是POJO“Plain Old Java Object”“简单java对象”。POJO的内在含义是指那些没有从任何类继承、也没有实现任何接口&#xff0c;更没有被其它框架侵入的java对象。二&#xff1a;为什么会有POJO&#xff1f;主要是Java的开发者被EJB的繁杂搞怕了&#xff0c;…

MATLAB调用C/C++函数的方法

http://item.taobao.com/item.htm?spma1z10.5-c.w4002-9510581626.24.ZO6sko&id43401674106 精通MATLAB混合编程视频讲解 MATLAB各类函数视频讲解 基于MATLAB的高等数学问题求解 MATLAB函数速查视频讲解 面向对象C视频教程 精通MATLAB混编编程demo及PDF QQ&#xff1a…

迁云架构实践

本文着笔介绍IT互联网化为传统企业带来的技术挑战&#xff0c;并对上云架构最佳实践进行了深入介绍&#xff0c;首发于阿里云&《程序员》联合出品的《凌云》杂志。 作者&#xff1a; 王宇德&#xff0c;张文生 云计算作为信息技术领域的一种创新应用模式&#xff0c;自其诞…

最短路最新心得

如果&#xff0c;上面的图&#xff0c;如果用dij算法&#xff0c;那么dist[4] 4, 是得不到正确的结果的&#xff0c; 这个因为dist[3]先被确定是最小&#xff0c;然后用来更新dist[4] 但是存在负权&#xff0c;使得dist[3]更小&#xff0c;但是我们已经把结点3标记为不可用了…

java canvas 缩放图片_java-GWT:放大和缩小画布绘图

我想应用放大和缩小,并在画布上重新绘制对象,以便在最大和最小缩放级别都能获得清晰的视图.我获得了如何执行操作的参考here,因此我已将画布传递给可缩放图像构造函数而不是图像,并按照所有步骤进行操作.我再次在“ mainDraw”方法中重画对象,但没有得到正确的结果.我知道我缺少…

MATLAB中MEX文件的编写与调试

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com http://item.taobao.com/item.htm?spma1z10.5-c.w4002-9510581626.24.ZO6sko&id43401674106 精通MATLAB混合编程视频讲解 MATLAB各类函数…

数据库设计思考

一&#xff1a;没有完美的数据库设计&#xff0c;只有符合业务的数据库设计&#xff01; 二&#xff1a;我们的数据库设计&#xff0c;在遵守标准&#xff08;三大范式&#xff09;的同时也要考虑客户的体验&#xff01; 有用户才有天下&#xff01; 三&#xff1a;数据库设计时…

performSegueWithIdentifier:sender里边的sender是啥意思

performSegueWithIdentifier:sender里边的sender是啥意思啊&#xff1f;怎样用啊&#xff1f; [self performSegueWithIdentifier:"pushSign" sender:self]; [self performSegueWithIdentifier:"pushSign" sender:sender]; [self performSegueWithIdent…

java wrapper怎么运行_如何从智能合约中生成Java Wrapper

在本文中&#xff0c;我们将了解如何直接从智能合约生成Java Wrapper类以与Java中的智能合约进行交互。从智能合约生成Java Wrapper类有不同的方法&#xff1a;1. Web3j命令行工具和solc2. Web3j命令行工具和Truffle构建生成的工件3. web3j-maven-plugin4. web3j-gradle-plugin…

Hive 1.2.1SparkSqoop安装指南

目录 目录 1 1. 前言 1 2. 约定 2 3. 服务端口 2 4. 安装MySQL 2 4.1. 安装MySQL 2 4.2. 创建Hive元数据库 4 5. 安装步骤 5 5.1. 下载Hive 1.2.1二进制安装包 5 5.2. 安装Hive 5 5.3. 安装MySQL-Connector 5 5.4. 修改配置 5 5.4.1. 修改/etc/profile或~/.profile 5 5.4.2. 修…

Matlab与C/C++混合编程调用OpenCV

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com http://item.taobao.com/item.htm?spma1z10.5-c.w4002-9510581626.24.ZO6sko&id43401674106 精通MATLAB混合编程视频讲解 MATLAB各类函数…

STL--排序与检索

题目 现有N个大理石&#xff0c;每个大理石上写了一个非负整数。首先把各数从小到大排序&#xff0c;然后回答Q个问题。每个问题是否有一个大理石写着某个整数x,如果是&#xff0c;还要回答哪个大理石写着x。排序后的大理石从左到右编写为1-N。&#xff08;样例中&#xff0c;…

体验LESS CSS 框架

LESS基于NODE.JS的一种框架性语言&#xff0c;它可以更好更快捷的来搭建网站框架结构&#xff1b; 而后LESS 将 CSS 赋予了动态语言的特性&#xff0c;如 变量&#xff0c; 继承&#xff0c;运算&#xff0c; 函数. LESS 既可以在 客户端 上运行 (支持IE 6, Webkit, Firefox)&a…

java添加按钮点击事件_如何为odoo 10中的按钮点击事件添加一个java脚本处理程序?...

我想使用java脚本为header中的按钮创建一个处理程序。下面我视图模型给出&#xff1a;如何为odoo 10中的按钮点击事件添加一个java脚本处理程序&#xff1f;inherit_id"web.assets_backend">rel"stylesheet">my_pet_store_formpetstore.messageformc…

LeetCode(53):Maximum Subarray

Maximum Subarray: Find the contiguous subarray within an array (containing at least one number) which has the largest sum.For example, given the array [−2,1,−3,4,−1,2,1,−5,4],the contiguous subarray [4,−1,2,1] has the largest sum 6. 题意&#xff1a;找…

孩子教育

看了一圈学区房&#xff0c;基本上把浦东各个一流二流学校全看一遍了&#xff0c;大体下来觉得未必非要到一流学校附近买学区房&#xff0c;主要是家庭经济条件不允许&#xff0c;再者我和老公希望孩子在小学培养读书的习惯&#xff0c;而不是天天做试卷。所以一流学校和二流学…

python 程序打包 vscode_使用VScode编写python程序并打包成.exe文件

听说Visual Studio Code(VS Code)的诸多好处&#xff0c;了解了一下果真很喜欢&#xff0c;我喜欢它的缘由主要有3个&#xff0c;一是VS Code开源且跨平台&#xff0c;二是由于其界面很是酷&#xff0c;三是能够知足个人大所属代码需求&#xff0c;除此以外固然还有强大的好奇心…