您的位置:首页 > 编程语言 > C#

C#4.0之dynamic的使用

2015-11-28 21:03 696 查看
在上一篇有关.Net 轻量 ORM Dapper 的介绍中我们提出了两个疑问,其中之一就是怎么让 Dapper 查询传参可变的问题,当然这里主要说是个数可变。这里我们就介绍C#4.0的新特性之一—— dynamic 。

C#4.0常用新特性

C#4.0引入了很多新特性方便我们进行开发,其中常用的包含以下四种。

可选参数

为方法的参数设定默认值,标识它是可选的,

public static void Show(string str1="str1",string str2="str2")
{
Console.WriteLine(str1 + str2);
}


命名参数

上面的方法可以像下面遮掩的
Show(str2:"msg");
运行结果:str1msg。当你的方法有多个同一类型的可选参数(optional parameters)时,命名参数(Named parameters)特别有用。如果不用命名参数,编译器会把传参赋给第一个符合类型的参数,运行结果就会是:msgstr2。

Dynamic 特性

dynamic关键字用于声明一个动态对象,然后通过该动态对象去调用方法或读写属性。以前我们都是在运行时通过反射,Emit,CodeDom等技术来完成。创建一个dynamic类型的对象需要使用一个特殊的构建器叫ExpandoObject。

dynamic person = new System.Dynamic.ExpandoObject();

person.Name = "cary";

person.Age = 25;

person.ShowDescription = new Func<string>(() => person.Name + person.Age);

Console.WriteLine(person.Name+person.Age+person.ShowDescription());

Console.ReadLine();


C#4.0之Dynamic介绍

dynamicl
类型可以很方便的随意插入字段、属性、方法。dynamic的出现让C#具有了弱语言类型的特性。dynamic类型的变量,不是在编译时候确定实际类型的, 而是在运行时。所以编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性。也就是说诸如下面的这两行代码,在程序编译时不会报错,而是在程序运行时报错:
dynamic a = "test";
a++;
这就要求我们在使用 dynamic 关键字时要特别小心。
在上面的例子中,细心的同学会发现 dynamic 类型需要借助 System.Dynamic.ExpandoObject 来实现,ExpandoObject() 是另一个重要的C#4.0特性之一,为了探讨这一特性,我们首先来看用dynamic增强C#泛型表达力中的一段代码:
static class Calculator {
public static T Add<T>(T t1, T t2) {
dynamic d1 = t1;
dynamic d2 = t2;

return (T)(d1 + d2);
}
}

public static void Main(string[] args){
int i = Calculator.Add(1, 2);
double d = Calculator.Add(1.1, 2.2);
string s = Calculator.Add("abc", "def");

Console.WriteLine(i + " " + d + " " + s);

}
作者在文中指出C#代码是为了通过动态类型来实现基于duck typing的泛型参数约束。ExpandoObject 是C#支持Duck Type的根本原因。在Visual Studio 2010 中我们可以看到该类的成员列表,截图如下:



所属方法都是虚方法,我们可以重写这些虚方法。这里主要看TryInvokeMember()方法。这个方法VS2010给出了详细的描述。

简单介绍一下如何使用这个方法:假设我们一个类OurClass它继承了DynamicObject 这个Class。OurClass中有一个方法OurMethod()。接着在OurClass 类中 重写 TryInvokeMember这个基类虚方法。以上设置完后以后只要OurClass 的OurMethod方法一旦被调用都先执行一下重写后的TryInvokeMember()方法。也许您会问这样到底有何用途?OK!请先看javascript这段代码片段:

function tryInvokeMember(obj) {
if (obj && typeof obj.ourMethod === "function") {
return obj.ourMethod();
}
alert('未找到!');
return null;
}

var ourObj1 = {};
ourObj1.Method = function () {
alert('111');
};

var ourObj2 = {};
ourObj2.ourMethod = function () {
alert('已经找到ourMethod并且执行');
};

tryInvokeMember(ourObj1);
tryInvokeMember(ourObj2);
大家读完这段js代码后应该会明白为什么我要重点讨论C#4.0中的DynamicObject了吧?真正的目的就是:在DuckType 类(鸭子) 方法(鸭子叫)执行之前,我们要判断对象的类是否是具备鸭子叫的功能?如果不具备就不应该执行,否则程序势必会抛出异常。C#中如何实现呢?步骤如下:

建立DynamicAnimal 类继承DynamicObject类,并且重写TryInvokeMember虚方法:

<strong>    </strong>public class DynamicAnimal : DynamicObject
{
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
bool success = base.TryInvokeMember(binder, args, out result);

//如果方法不存在,请将result 这个out参数赋值为null
if (!success)
result = null;

//如果这个地方返回false 将会引发异常
return true;
}
}

建立两个DuckType类,分别为Duck 和 Human:

public class Duck : DynamicAnimal
{
public string Quack()
{
return "鸭子嘛,就Quack吧!";
}
}
public class Human : DynamicAnimal
{
public string Talk()
{
return "人类是用Talk,而不是Quack";
}
}

在Console 内 建立DuckType的调用方法:

public static string DoQuack(dynamic animal)
{
string result = animal.Quack();
return result ?? "...人类当然不会鸭叫...";
}

Console 内 Main方法调用:

static void Main(string[] args)
{
var duck = new Duck();
var cow = new Human();
Console.WriteLine("鸭子是Quack");
Console.WriteLine(DoQuack(duck));
Console.WriteLine("人类是talk");
Console.WriteLine(DoQuack(cow));
Console.ReadKey();
}


程序的执行结果如下:



var、object、dynamic比较

在语法上这三者的用法很相近
var a=1;
object a=1;
dynamic c=1;
以及
var a = new string[]{"1"};
object b = new string[]{"1"};
dynamic c = new string[]{"1"};
比较一下有助于记忆。
var是C# 3中引入的,其实它仅仅只是一个语法糖. var本身并不是一种类型, 其它两者object和dynamic是类型。var声明的变量在赋值的那一刻,就已经决定了它是什么类型。所以如果你这样使用,就会有编译错误:

var a = 1;
a = "Test";
object之所以能够被赋值为任意类型的原因,其实都知道,因为所有的类型都派生自object. 所以它可以赋值为任何类型:
object a = 1;
a = "Test";
dynamic是C#引入的新类型,它的特点是申明为dynamic类型的变量,不是在编译时候确定实际类型的, 而是在运行时。所以下面的代码是能够通过编译的,但是会在运行时报错:
dynamic a = "test";
a++;
上面代码内部处理的过程是怎样的呢?首先, dynamic类型赋值为字符串"test", 运行++操作的时候,.net会去寻找当前的赋值类型string中是否支持++操作,发现不支持,出现异常。所以,如果这样修改一下,就可以让代码正常运行起来。

dynamic a = "test";
a = 1;
a++;


结语

以上的探讨是从使用角度出发对 C#4.0 新特性 dynamic 进行的介绍,若要对 dynamic 有更全面的理解,可以移步微软的msdn官方文档上查看 dynamic 更专业的介绍。
传送门:

dynamic(C# 参考)https://msdn.microsoft.com/zh-cn/library/dd264741.aspx

使用类型 dynamic(C# 编程指南) https://msdn.microsoft.com/zh-cn/library/dd264736.aspx

参考博客:

http://www.cnblogs.com/weidagang2046/archive/2010/11/21/1883032.html

http://www.cnblogs.com/ryanding/archive/2010/12/09/1900106.html

http://www.cnblogs.com/luminji/archive/2011/02/18/1957484.html

http://www.cnblogs.com/JustRun1983/p/3163350.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: