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

dynamic

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

调用不同类的相同方法

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

 using System;

 namespace Study
{
class Program
{
static void Main(string[] args)
{
dynamic obj = GetObject();
Console.WriteLine(obj.Talk()); Console.Read();
} private static Object GetObject(int type)
{
switch (type)
{
case :
return new Dog();
}
return new Robot();
}
} public class Dog
{
public string Talk()
{
return "Wang Wang!";
}
} public class Robot
{
public string Talk()
{
return "I`m a Robot!";
}
}
}

我们的两个类没有继承也没有应用相同的接口,但是可以调用到相同的方法,使用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类来实现动态行为,代码如下:

 using System;
using System.Dynamic; namespace Study
{
class Program
{
static void Main(string[] args)
{
dynamic obj = new ExpandoObject();
//添加属性
obj.name = "Li Lei";
obj.age = ;
//添加方法
obj.Add = (Func<int, int, int>) ((a, b) => a + b); Console.WriteLine("Name: " + obj.name);
Console.WriteLine("Age: " + obj.age);
Console.WriteLine("Add: " + obj.Add(, )); Console.Read();
}
}
}

输出如下:

 Name: Li Lei
Age:
Add:

继承DynamicObject类

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

 using System;
using System.Dynamic; namespace Study
{
class Program
{
static void Main(string[] args)
{
dynamic obj = new MyClass();
obj.name = "Li Lei";
obj.age = ;
obj.CallFunc(); Console.Read();
}
} public class MyClass : DynamicObject
{
public override bool TrySetMember(SetMemberBinder binder, object value)
{
Console.WriteLine("设置" + binder.Name + "为" + value);
return true;
} public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
Console.WriteLine("调用" + binder.Name + "方法");
result = null;
return true;
}
}
}

输出如下:

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

实现IDynamicMetaObjectProvider接口

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

 using System;
using System.Dynamic;
using System.Linq.Expressions; namespace Study
{
class Program
{
static void Main(string[] args)
{
dynamic obj = new MyClass();
obj.CallFunc(); Console.Read();
}
} public class MyClass : IDynamicMetaObjectProvider
{
public DynamicMetaObject GetMetaObject(Expression parameter)
{
Console.WriteLine("获取元数据");
return new MetaDynamic(parameter, this);
}
} public class MetaDynamic : DynamicMetaObject
{
public MetaDynamic(Expression expression, object value) : base(expression, BindingRestrictions.Empty, value)
{
} public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
MyClass target = base.Value as MyClass;
Expression self = Expression.Convert(base.Expression, typeof (MyClass));
var restrictions = BindingRestrictions.GetInstanceRestriction(self, target);
Console.WriteLine("调用" + binder.Name + "方法");
return new DynamicMetaObject(self, restrictions);
}
}
}

输出如下:

 获取元数据
调用CallFunc方法

C#学习笔记(十一):动态类型的更多相关文章

  1. Web Service学习笔记:动态调用WebService

    原文:Web Service学习笔记:动态调用WebService 多数时候我们通过 "添加 Web 引用..." 创建客户端代理类的方式调用WebService,但在某些情况下我 ...

  2. python3.4学习笔记(十一) 列表、数组实例

    python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...

  3. Go语言学习笔记十一: 切片(slice)

    Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...

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

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

  5. [C++学习笔记14]动态创建对象(定义静态方法实现在map查找具体类名对应的创建函数,并返回函数指针,map真是一个万能类)good

    [C++学习笔记14]动态创建对象   C#/Java中的反射机制 动态获取类型信息(方法与属性) 动态创建对象 动态调用对象的方法 动态操作对象的属性 前提:需要给每个类添加元数据 动态创建对象 实 ...

  6. java学习笔记01--数据类型

    java学习笔记01--数据类型 java数据类型划分 分为两大类型: 1)基本数据类型:类似于普通的值. 2)引用数据类型:传递的是内存的地址. 浮点类型实际上就是表示小数. java基本数据类型 ...

  7. Hadoop学习笔记—5.自定义类型处理手机上网日志

    转载自http://www.cnblogs.com/edisonchou/p/4288737.html Hadoop学习笔记—5.自定义类型处理手机上网日志 一.测试数据:手机上网日志 1.1 关于这 ...

  8. C#学习笔记之值类型与引用类型

    [TOC] C#学习笔记之值类型与引用类型 1.值类型与引用类型 1.1 深层区别 值类型与引用类型有不同的内存分布,这导致了不同的内存管理机制: 值类型由OS负责内存管理 引用类型由垃圾回收器(GC ...

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

    MyBatis:学习笔记(4)——动态SQL 如果使用JDBC或者其他框架,很多时候需要你根据需求手动拼装SQL语句,这是一件非常麻烦的事情.MyBatis提供了对SQL语句动态的组装能力,而且他只有 ...

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

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

随机推荐

  1. UVa 524 Prime Ring Problem【回溯】

    题意:给出n,把从1到n排成一个环,输出相邻两个数的和为素数的序列 照着紫书敲的, 大概就是这个地方需要注意下,初始化的时候a[0]=1,然后dfs(1),从第1个位置开始搜 #include< ...

  2. IIS Web负载均衡的几种方式

    Web负载均衡的几种实现方式 摘要:负载均衡(Load Balance)是集群技术(Cluster)的一种应用.负载均衡可以将工作任务分摊到多个处理单元,从而提高并发处理能力.目前最常见的负载均衡应用 ...

  3. Jquery 模板插件 jquery.tmpl.js 的使用方法(1):基本语法,绑定,each循环,ajax获取json数据

    jquery.tmpl.js 是一个模板js  ,主要有2个方法 (1):$.template()方法,将一段script或者是Html编译为模板,例如 $.template('myTemplate' ...

  4. qtcreator cannot find -lts

    /********************************************************************* * qtcreator cannot find -lts ...

  5. win32 摄像头捕获系统vfw

    //win32 摄像头捕获系统vfw //  VideoRecord.h ///  用于定义一些资源ID #include "resource.h" //#define EXIT  ...

  6. Jquery获取第一个子元素

    如获取id为divId的div下的第一个子div $("#divId").children("div").get(0) 但得到的是一个dom对象,如果要得到Jq ...

  7. 底部菜单栏(二) TabHost & RadioGroup 实现

    需求:使用TabHost & RadioGroup实现底部菜单栏: 效果图: 实现分析: 1.目录结构: 代码实现: 1. activity_main.xml <?xml version ...

  8. hdu 5335 Walk Out(bfs+斜行递推) 2015 Multi-University Training Contest 4

    题意—— 一个n*m的地图,从左上角走到右下角. 这个地图是一个01串,要求我们行走的路径形成的01串最小. 注意,串中最左端的0全部可以忽略,除非是一个0串,此时输出0. 例: 3 3 001 11 ...

  9. webdriver(python) 学习笔记三

    知识点:简单的对象定位 对象的定位应该是自动化测试的核心,要想操作一个对象,首先应该识别这个对象.一个对象就是一个人一样,他会有各种的特征(属性),如比我们可以通过一个人的身份证号,姓名,或者他住在哪 ...

  10. Maximum Random Walk(概率dp)

    题意: 走n步,给出每步向左走概率l,向右走概率r,留在原地的概率 1-l-r,求能达到的最远右边距离的期望. 分析: 开始按期望逆求的方式分析,但让求的就是右边界没法退,懵了一会,既然逆着不能求,就 ...