中dynamic的正确用法,编制程序总括

dynamic是FrameWork四.0的新特点。dynamic的产出让C#装有了弱语言类型的特性。编译器在编写翻译的时候不再对品种进行自小编批评,编写翻译期暗许dynamic对象帮衬你想要的别样个性。比如,即使你对GetDynamicObject方法再次来到的目的一窍不通,你也足以像如下那样进行代码的调用,编写翻译器不会报错:

dynamic是FrameWork四.0的新特征。
dynamic的面世让C#拥有了弱语言类型的风味。编写翻译器在编译的时候不再对品种进行自笔者批评,编写翻译期默许dynamic对象帮衬你想要的其余特性。比如,
即便你对GetDynamicObject方法重返的靶子一无所知,你也足以像如下那样进行代码的调用,编写翻译器不会报错:

C#编制程序计算(十4)dynamic

让我们飞快看看object关键字先。笔者不会对它讲太多,因为它在C#1.0就已经有了。这些至关心注重要字没有越来越多东西除了作为System.Object的快速方式,System.Object是C#类层次的根类型。(可是,正如埃里克Lippert在他博客中提出,不要任何类型都三番五次源于object[中][英])这是一个有力的机制,那样您大概能够分配任何实例值到此类型。

dynamic dynamicObject = GetDynamicObject();
Console.WriteLine(dynamicObject.Name);
Console.WriteLine(dynamicObject.SampleMethod());

 

介绍

Visual
C# 2010 引进了二个新品类 dynamic。 该类型是一种静态类型,但品种为 dynamic 的指标会跳过静态类型检查。 当先四分之三动静下,该指标就像是全部类型 object 一样。 在编写翻译时,将假定类型化为 dynamic 的成分支持任何操作。 由此,您不用挂念对象是从
COM API、从动态语言(例如 IronPython)、从 HTML 文书档案对象模型
(DOM)、从反射依旧从程序中的别的岗位获取自个儿的值。 可是,若是代码无效,则在运作时会捕获到错误。

 

那是个小例子用来演示使用object关键字的便宜和难点。

dynamic与var关键字本质分化

var只可以用作壹些变量,不可能用来字段,参数;评释的同时必须伊始化;初阶化时类型就已经明确了,并且不能再被赋值不能够进行隐式类型转换的项指标数目。

var实际上是编写翻译期抛给大家的“语法糖”,一旦被编写翻译,编写翻译期会自动相称var
变量的莫过于类型,并用实际类型来替换该变量的评释,那看起来就就像大家在编码的时候是用实际类型实行表达的。

dynamic可用以项指标字段,方法参数,方法重临值,可用于泛型的门类参数等;能够赋值给或被赋值任何项目并且不必要显式的恐吓类型转换,因为这么些是运行时举行的,那要得益于dynamic类型的动态天性。

dynamic被编写翻译后,实际是2个object类型,只可是编写翻译器会对dynamic类型进行卓殊规处理,让它在编写翻译期间不实行别的的花色检查,而是将项目检查放到了运营期。

从visual
studio的编辑器窗口就能看出来。以var申明的变量,扶助“智能感知”,因为visual
studion能揣摸出var类型的实际上类型,而以dynamic评释的变量却不补助“智能感知”,因为编写翻译器对其运行期的花色一窍不通。对dynamic变量使用“智能感知”,会唤醒“此操作将在运维时分析”。

dynamic
dynamicObject = GetDynamicObject();
Console.WriteLine(dynamicObject.Name);
Console.WriteLine(dynamicObject.SampleMethod());

var与dynamic对比

一、var编写翻译时替换为实在类型,而dynamic实际是object类型。

借使被编写翻译,编写翻译期会自动匹配var
变量的实际上类型,并用实际类型来替换该变量的发明,那看起来就就如大家在编码的时候是用实际类型实行表明的。而dynamic被编写翻译后,实际是三个object类型,只然而编写翻译器会对dynamic类型举办11分处理,让它在编写翻译期间不开始展览其它的品类检查,而是将品种检查放到了运营期。

二、智能感知。

以var评释的变量,扶助“智能感知”,因为visual
studion能推测出var类型的其实类型,而以dynamic表明的变量却不援助“智能感知”,因为编写翻译器对其运维期的门类一窍不通。对dynamic变量使用“智能感知”,会唤醒“此操作将在运转时解析”。

 

object obj = 10;

Console.WriteLine(obj.GetType());

// 输出 System.Int32 因为

// 那是其一指标里积存的值的项目。

// 一个编写翻译错误, 因为 

// 在编写翻译时obj的类型是System.Object。

// obj = obj + 10;

中dynamic的正确用法,编制程序总括。// 你必要显式转换obj到希望的档次。

obj = (int)obj + 10;

// 然则, 那样并不意味您确实安全。 

// 你恐怕转换到一个荒谬的档次 

// 而编写翻译器并不会发现。 

// 那里您会在运维时获得2个非常, 

// 因为obj是int类型,不是string类型。

// obj = (string)obj + 10;

// 要是你将其转移到贰个不当的数值类型, 

// 你也会取得3个运转时丰硕 

// 固然有隐式转换的语法在那里。

// obj = (double)obj + 10;

类型转换

Dynamic类型的实例和任何门类的实例间的更换是很简单的,开发人员能够很有益地在dyanmic和非dynamic行为间切换。任何实例都能隐式转换为dynamic类型实例,见上面包车型地铁事例:

dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();

Conversely, an implicit conversion can be dynamically applied to any
expression of type dynamic.
反之相同,类型为dynamic的此外表明式也能够隐式转换为任何品种。

int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;

说起正确用法,那么首先应当提出贰个张冠李戴用法:

粗略案例

编辑2个hello
world的测试程序,定义DynamicTest类型,并扩大Welcome方法,其参数为name.

接下来创造dynamic对象,调用Welcome方法。参数为空。

using System;


namespace DynamicSample
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic obj = new DynamicTest();
            obj.Welcome();
        }
    }

    class DynamicTest
    {
        public void Welcome(string name)
        {
            Console.WriteLine("Hello {0},welcome to dynamic world.",name);
        }
    }
}

探访发生哪些业务啊,通过测试发现:

编写翻译通过,未有其余尤其。

运行时抛出卓殊,十分消息:

未处理Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
  HResult=-2146233088
  Message=“Welcome”方法没有采用“0”个参数的重载
  Source=Anonymously Hosted DynamicMethods Assembly
  StackTrace:
       在 CallSite.Target(Closure , CallSite , Object )
       在 System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0)
       在 DynamicSample.Program.Main(String[] args) 位置 E:\Donet\C#\DynamicSample\DynamicSample\Program.cs:行号 13
       在 System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       在 System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

修正后:

    class Program
    {
        static void Main(string[] args)
        {
            dynamic obj = new DynamicTest();
            string name = "Tom";
            obj.Welcome(name);

            Console.WriteLine("Input any key to exit.");
            Console.ReadKey();
        }
    }

运作结果:

亚洲必赢官网 1

 

一经改为var,定义该对象,并调用方法,代码如下,编写翻译器会报错:

            var v1 = new DynamicTest();
            v1.Welcome();

错误音信:

    错误    CS7036    未提供与“DynamicTest.Welcome(string)”的必需形参“name”对应的实参    DynamicSample    Program.cs    15
    错误    CS7036    There is no argument given that corresponds to the required formal parameter 'name' of 'DynamicTest.Welcome(string)'    DynamicSample    

 

您能够看出,尽管obj存款和储蓄叁个int值,即使未有更换,编写翻译器依旧不会让您执行别的数学操作。它看起来好像是扶持您分明是或不是你真有一个int类型,但它不是。你能够变换来二个完全两样的种类但编译器却检查不出。结果正是,你获取3个周转时那三个。

措施中蕴藏dynamic类型参数的重载难点

若是调用二个办法是传递了dynamic类型的指标,恐怕被调用的靶子是dynamic类型的,那么重载的判断是发生在运维时而不是编写翻译时。
动态语言运转时(dynamic language runtime DL凯雷德)动态语言运维时是.NET
Framework 4 Beta
第11中学的1组新的API,它提供了对c#中dynamic类型的支持,也落到实处了像IronPython和IronRuby之类的动态程序设计语言。

有史以来人会拿var那一个重大字来和dynamic做相比。实际
上,var和dynamic完全是八个概念,根本不应该置身一起做相比较。var实际上是编写翻译期抛给大家的“语法糖”,一旦被编写翻译,编写翻译期会自动相称var
变量的实在类型,并用实际类型来替换该变量的评释,那看起来就像大家在编码的时候是用实际类型举办表达的。而dynamic被编写翻译后,实际是四个object类型,只不过编写翻译器会对dynamic类型进行十一分处理,让它在编写翻译时期不开始展览其余的门类检查,而是将项目检查放到了运转期。

dynamic应用范围

一、在表明中,作为性能、字段、索引器、参数、再次回到值或项目约束的项目,都足以使用dynamic。

二、在显式类型转换中,作为转换的对象项目。任何对象都得以隐式转为dynamic。

三、在以项目充当班值日(如 is 运算符或 as 运算符左侧)或然作为 typeof 的参数成为构造类型的一部分的别样上下文中。

通过2个实例来具体表达:

    class DynamicUser
    {
        /// <summary>
        /// 字段
        /// </summary>
        public dynamic userid;

        /// <summary>
        /// 属性
        /// </summary>
        public dynamic UserName { get; set; }

        /// <summary>
        /// 玩游戏
        /// (dynamic可以作为参数、返回值等)
        /// </summary>
        /// <param name="game"></param>
        /// <returns></returns>
        public dynamic Play(dynamic game)
        {
            dynamic defaultGame = "Play Basketball.";

            dynamic secGame = "Play with mud.";

            if (game is int)
            {
                return defaultGame;
            }
            else
            {
                return secGame;
            }
        }
        /// <summary>
        /// 显式类型转换
        /// </summary>
        public void ConvertToDynamic(object obj)
        {
            dynamic d;
            d = (dynamic)obj;
            Console.WriteLine(d);
        }
        /// <summary>
        /// 类型判定
        /// (dynamic 可以使用is、as、typeof)
        /// </summary>
        public void TypeCheck()
        {
            int age = 20;
            Console.WriteLine("Age is Dynamic? {0}",age is dynamic);

            dynamic d = age as dynamic;
            Console.WriteLine("Age:{0}",d);         

            Console.WriteLine("List<dynamic>'s type is {0}",typeof(List<dynamic>));
        }

    }

测试用例:

            DynamicUser user = new DynamicUser();
            user.userid = 123;
            user.UserName = "Lucy";
            user.ConvertToDynamic(user.userid);
            user.ConvertToDynamic(user.UserName);
            user.TypeCheck();

            Console.WriteLine("Input any key to exit.");
            Console.ReadKey();

测试结果:
亚洲必赢官网 2

 

故而你只可以施行呈现转换,那并不保障什么,仅仅因为假设不更换,编写翻译器不会让您运营。

dynamic 简化反射

先前小编们这么使用反射:

public class DynamicSample
{
public string Name { get; set; }

public int Add(int a, int b)
{
return a + b;
}
}
DynamicSample dynamicSample = new DynamicSample(); //create instance为了简化演示,我没有使用反射
var addMethod = typeof(DynamicSample).GetMethod("Add");
int re = (int)addMethod.Invoke(dynamicSample, new object[] { 1, 2 });

前几日,大家有了简化的写法:

dynamic dynamicSample2 = new DynamicSample();
int re2 = dynamicSample2.Add(1, 2);

那从visual
studio的编辑器窗口就能看出来。以var声明的变量,扶助“智能感知”,因为visual
studion能估算出var类型的骨子里类型,而以dynamic申明的变量却不协助“智能感知”,因为编写翻译器对其运转期的品种一无所知。对
dynamic变量使用“智能感知”,会唤起“此操作将在运作时分析”。

 dynamic的履行成效

有关dynamic的频率难点,那里暂不展开,后续专门来探讨…

新的dynamic关键字来了。它告诉编译器不要强制附加规则在您的代码上。

var,dynamic,守旧分明项指标频率相比较

古板类其他频率 >= var动态类型 > dynamic动态类型

编写翻译器对dynamic举行了优化,比尚未通过缓存的反光作用高。

参考文章:

有关dynamic变量是二个object变量那一点,能够经过IL代码获得证实,那里不再贴出IL代码。当然,编写翻译器也对dynamic评释举办了拍卖,以界别直接object变量。

应用

1、自动反射

2、COM组件互操作

三、混合编制程序,例如IronRuby和IronPython

4、处理Html DOM对象

5、还有一种接纳,数据传输中格式转换,如:对象转json等,很有益于

 

 

dynamic是做为简化互操作性而被MSDN中山大学四渲染,
小编觉得便是依照那一点,才被部分开发职员误解:因为众多开发职员不会接触COM+、OFFICE一次支付之类的编码,所以急需求二个dynamic的接纳理由。那么,在常常费用中,笔者认为dynamic很有价值的少数是:

dynamic dyn = 10;

Console.WriteLine(dyn.GetType());

// 跟”object”一样. 

// 输出 System.Int32 因为

// 这是这几个目的里积存的值的项目。

// 未有编写翻译错误,因为 

// 编写翻译器不会在编写翻译时

// 试图识别dynamic对象的系列。

dyn = dyn + 10;

 

// 同样,那么些操作会在富有数值或

// 别的帮助“+”操作符的连串上打响运算。

dyn = 10.0;

dyn = dyn + 10;

dyn = “10”;

dyn = dyn + 10;

 

类型转换

这是1个object和dynamic间的关键分裂—-用dynamic约等于你告知编写翻译器此指标的品种只在运维时规定,编译器不会试图干预。最后,你能够写更加少的代码。但自个儿要强调一下,相对于采用原有的object关键字,那样做不会大增其余危险。同样,也不会回落别的危险,所以当操作任何对象要求类型检查技术时(如反射),则利用dynamic对象会更加好。

Dynamic类型的实例和其它项目标实例间的转移是很简短的,开发人士能够很有益于地在dyanmic和非dynamic行为间切换。任何实例都能隐式转换为dynamic类型实例,见上边的例证:

接下去一般晤面世如下难题:“既然dynamic对象足以是任意对象并且编写翻译器不会检查它是怎样,那是否意味着你能够传递贰个dynamic对象给自个儿的深信措施/系统并使它崩溃?”

dynamic d1 = 7;

让大家只要拥有三个归纳方法。

dynamic d2 = “a string”;

 

dynamic d3 = System.DateTime.Today;

public static void Print(string arg)

{

         Console.WriteLine(arg);

}

 

dynamic d4 = System.Diagnostics.Process.GetProcesses();

现行大家看看您能怎么传递dynamic对象给它。

Conversely, an implicit conversion can be dynamically applied to any
expression of type dynamic.

 

反之相同,类型为dynamic的任何表明式也能够隐式转换为其它类型。

dynamic dyn = 10;

// 你将于运作时在此地获得一个分外.

Print(dyn);

 

int i = d1;

你能够看见,尽管编写翻译器允许你传递三个dynamic对象给你的不二秘诀,但您的格局永远不会获取那个目的倘使它是个错误的体系。在章程其实执行从前曾经有贰个尤其抛出。惟有当它包涵一个安妥班值日时,你才能传递dynamic对象给你的主意,在此处是string类型。

string str = d2;

 

dynamic dyn = “10”;

Print(dyn);

 

DateTime dt = d3;

重新强调,这跟你使用object关键字比较不会有太多作为上的区分。

System.Diagnostics.Process[] procs = d4;

 

// 不会编写翻译通过.

//Print(obj);

// 编写翻译, 但那里在运维时会有个卓殊。

//Print((string)obj);

// 那里的代码会正常办事,因为将来obj是个string型,

// 但你不须要转移。

obj = “10”;

Print((string)obj);

 

办法中涵盖dynamic类型参数的重载难点

有人说(int)obj那种写法并不难通晓,为何要再来个dynamic呢?好吧,有个别情状下您不得不施行较多的更换操作,那使得你的代码很难理解。还有个别意况下简单的变换并不能够落得指标,你要求调用反射方法,比如InvokeMember或GetProperties。二个很好的例证就是COM互操作,那正是为什么它要修改以使用新dynamic天性(越多消息点那里“how-to”.aspx))。

亚洲必赢官网 ,1经调用三个措施是传递了dynamic类型的目的,只怕被调用的指标是dynamic类型的,那么重载的论断是发出在运作时而不是编写翻译时。

同时,用dynamic关键字和dynamic语言运维时让很多在先不容许完成或难以实现的方案变得实惠,包涵与动态语言互操作。小编在事先的博客里强调过那八个情景: Introducing
ExpandoObject 和Creating
Wrappers with
DynamicObject.

动态语言运转时(dynamic language runtime DL福特Explorer)

您可能想去MSDN
walkthrough.aspx)看看,它彰显你该怎么从C#和Visual
Basic调用IronPython库,2个当真很酷的牵线,Using Dynamic Languages to
Build Scriptable
Applications,作者Dino
Viehland。另三个好的介绍体现壹些例证并表达设计基准背后是以此特点Dynamic
Binding in C#
4,作者Mads
Torgersen。

动态语言运维时是.NET Framework 四 Beta
第11中学的一组新的API,它提供了对c#中dynamic类型的支撑,也兑现了像IronPython和IronRuby之类的动态程序设计语言。

敲定是我们不须要担心会有人能用dynamic性情破坏你的代码。它并未有更加多(同时,也不曾更加少)的生死存亡相对于object关键字。

dynamic能够简化反射

故而,假如您时不时选拔object关键字并且只好施行一群转换”并且/或许”使用反射来调用对象的措施或品质,你大概应该注意一下dynamic关键字。在诸多时候它比object更便于而且编写更加少的代码。

先前作者们如此使用反射:

原稿未有提到var关键字,相信广大人会在这时想到var。

 

var在C#3.0中生出,其在MSDN中的定义:在点子范围中声称的变量能够拥有隐式类型
var。隐式类型的地点变量是强类型变量(就恍如你已经宣称该品种1样),但由编写翻译器显著项目。

亚洲必赢官网 3

选取var关键字注解变量,编写翻译器会依照分配的实例类型明确此变量的品类,即类型揣度。

public class
DynamicSample
{
public string Name {
get; set; }

 

var va = 10;

Console.WriteLine(va.GetType());

// 输出 System.Int32 因为

// 那是以此指标里储存的值的品种。

// 而va的编写翻译时类型也已经被编写翻译器明确为int型。

// 未有编写翻译错误,因为 

// va在率先句赋值时

// 便被编写翻译器鲜明其项目是int。

va = va + 10;

// 编写翻译错误,因为

// va变量已经规定是int型,而十.0是double型,

// 且double型向int型不可隐式转换。

// va = 10.0;

 

public int Add(int a, int b)
{
return a

跟object比,var属于强类型;

  • b;
    }
    }
    DynamicSample dynamic萨姆ple = new Dynamic萨姆ple(); //create
    instance为了简化演示,笔者平昔不动用反射
    var addMethod = typeof(DynamicSample).GetMethod(“Add”);
    int re = (int)addMethod.Invoke(dynamicSample, new object[] { 1, 2
    });

跟dynamic比,var并无任何运转时的动态性格,仅仅是编写翻译器在编写翻译时反向推断其连串,同直接用其编写翻译时类型注脚变量功能上是同1的。它独自是编写翻译器提供的语法糖。dynamic可不是语法糖,dynamic是急需周转时援救的。

亚洲必赢官网 4

 

方今,我们有了简化的写法:

VAQX56 是三.五新出的三个定义变量的花色
其实也正是弱化类型的概念
VAOdyssey可代替任何项目
编写翻译器会基于上下文来判断你到底是想用什么类型的

dynamic
dynamicSample2 = new DynamicSample();

至于什么情状下用到VA猎豹CS陆 作者想就是你不只怕分明本身将用的是怎么着品种
就足以行使VAPAJERO 类似 OBJECT
可是功能比OBJECT高点

int re2

dynamicSample2.Add(1, 2);

大家大概会对如此的简化漠然置之,毕竟看起来代码并未滑坡多少,可是,倘使设想到功效兼精彩三个特征,那么dynamic的优势就显现出来了。编写翻译器对dynamic举办了优化,比尚未经过缓存的反光成效快了许多。如若非要比较,能够将上面两者的代码(调用Add方法有个别)运营一千000就能够得出结论。

应用var定义变量时有以下多个特征:

  1. 总得在概念时起首化。也正是必须是var s =
    “abcd”情势,而不能是之类方式:

var s;

s = “abcd”;

  1. 一但开首化完成,就不可能再给变量赋与发轫化值类型差异的值了。

  2. var供给是有的变量。

肆.
用到var定义变量和object区别,它在功效上和行使强类型格局定义变量完全相同。

 

var表示“变量的花色是在编写翻译时间控制制的”,可是dynamic表示“变量的连串是在运行时间控制制的”。由此,dynamic与var具有完全区别的含义。 

var让你在初步化变量时少输入壹些字,编写翻译器会基于右值来揆度出变量的种类。dynamic更决定,它报告编写翻译器,根本就别理毕竟是啥类型,运行时再估量不迟。

var只好用来局地变量的概念,你不能够把类的习性定义成
var,也无法把艺术的归来值类型可能是参数类型定义成var。dynamic就不曾这么些局限了。

dynamic类型并未有跳过类型校验,只是延迟到了运营时。如若在运作时,检测到项目不包容,照样会抛出相当。

您大概在以下景况下使用dynamic:

1.COM对象

二.动态语言(如IronPython,IronRuby等)对象

三.反光对象

4.C# 四.0中动态创设的目的

网站地图xml地图