威尼斯人线上娱乐

动态目的,中dynamic的没有错用法

16 4月 , 2019  

dynamic是FrameWork4.0的新特征。dynamic的面世让C#装有了弱语言类型的特点。编写翻译器在编写翻译的时候不再对项目进行反省,编写翻译期暗中同意dynamic对象帮衬您想要的别样天性。比如,固然你对GetDynamicObject方法重临的目的一窍不通,你也足以像如下那样举办代码的调用,编译器不会报错:

dynamic是FrameWork肆.0的新天性。
dynamic的面世让C#不无了弱语言类型的性状。编写翻译器在编写翻译的时候不再对品种进行自小编批评,编译期私下认可dynamic对象协理你想要的其余本性。比如,
就算你对GetDynamicObject方法再次来到的对象一窍不通,你也能够像如下那样实行代码的调用,编写翻译器不会报错:

C#编程总括(10四)dynamic

让我们非常快看看object关键字先。笔者不会对它讲太多,因为它在C#一.0就曾经有了。那个重点字未有越来越多东西除了作为System.Object的神速方式,System.Object是C#类层次的根类型。(但是,正如埃里克Lippert在她博客中提议,绝不壹切类型都持续源于object[中][英])那是1个壮大的机制,这样您差不多能够分配任何实例值到此类型。

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

 

介绍

Visual
C# 20十 引进了三个新品类 dynamic。 该项目是一种静态类型,但品种为 dynamic 的靶子会跳过静态类型检查。 大诸多状态下,该指标就像是全部类型 object 一样。 在编写翻译时,将假定类型化为 dynamic 的成分接济任何操作。 由此,您不要牵挂对象是从
COM API、从动态语言(例如 IronPython)、从 HTML 文书档案对象模型
(DOM)、从反射仍然从程序中的其余职位获取自个儿的值。 不过,就算代码无效,则在运作时会捕获到错误。

 

那是个小例子用来演示使用object关键字的补益和主题材料。

dynamic与var关键字本质分裂

var只好用作1些变量,不可能用于字段,参数;表明的同时务必初叶化;开头化时类型就早已明显了,并且无法再被赋值无法拓展隐式类型转变的类其他数目。

var实际上是编译期抛给大家的“语法糖”,壹旦被编写翻译,编写翻译期会自动相配var
变量的实际类型,并用实际类型来替换该变量的阐发,那看起来就恍如大家在编码的时候是用实际类型进行表达的。

dynamic可用来项指标字段,方法参数,方法再次回到值,可用以泛型的档次参数等;能够赋值给或被赋值任何类型并且不须要显式的劫持类型调换,因为这个是运转时实行的,那要得益于dynamic类型的动态性情。

dynamic被编写翻译后,实际是1个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类型实行特殊处理,让它在编写翻译时期不开始展览别的的类型检查,而是将品种检查放到了运转期。

2、智能感知。

以var阐明的变量,接济“智能感知”,因为visual
studion能揣测出var类型的实在类型,而以dynamic评释的变量却不帮忙“智能感知”,因为编写翻译器对其运维期的品种一窍不通。对dynamic变量使用“智能感知”,会唤醒“此操作就要运作时解析”。

 

object obj = 10;

Console.WriteLine(obj.GetType());

// 输出 System.Int32 因为

// 那是这么些目标里积存的值的类型。

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

// 在编译时obj的档次是System.Object。

// obj = obj + 10;

// 你须要显式转变obj到梦想的品类。

obj = (int)obj + 10;

// 然则, 那样并不意味你实在安全。 

// 你可能调换成3个错误的体系 

// 而编写翻译器并不会意识。 

// 那里你会在运作时获得一个特别, 

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

// obj = (string)obj + 10;

// 就算你将其改动来八个荒唐的数值类型, 

动态目的,中dynamic的没有错用法。// 你也会博得一个周转时那么些 

// 尽管有隐式转变的语法在那边。

// 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;

聊起正确用法,那么首先应当建议三个不当用法:

轻松案例

编写1个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类型,但它不是。你能够调换成三个一心差别的品类但编写翻译器却检查不出。结果便是,你取得八个周转时丰盛。

办法中包含dynamic类型参数的重载难点

如果调用多个方法是传递了dynamic类型的指标,也许被调用的指标是dynamic类型的,那么重载的论断是发出在运作时而不是编写翻译时。
动态语言运维时(dynamic language runtime DL奥迪Q3)动态语言运维时是.NET
Framework 4 Beta
第11中学的一组新的API,它提供了对c#中dynamic类型的支撑,也促成了像IronPython和IronRuby之类的动态程序设计语言。

根本身会拿var这么些至关心尊崇要字来和dynamic做相比较。实际
上,var和dynamic完全是多少个概念,根本不应有献身一同做比较。var实际上是编译期抛给大家的“语法糖”,壹旦被编写翻译,编写翻译期会自动匹配var
变量的骨子里类型,并用实际类型来替换该变量的证明,那看起来就接近大家在编码的时候是用实际类型举办表明的。而dynamic被编译后,实际是一个object类型,只但是编写翻译器会对dynamic类型实行出格处理,让它在编写翻译时期不实行别的的品类检查,而是将品种检查放到了运转期。

dynamic应用范围

1、在注明中,作为品质、字段、索引器、参数、再次回到值或项目约束的类型,都能够行使dynamic。

2、在显式类型转变中,作为调换的靶子项目。任何对象都足以隐式转为dynamic。

三、在以种类充当班值日(如 is 运算符或 as 运算符右边)或然当作 typeof 的参数成为构造类型的1部分的其他上下文中。

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

    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、自动反射

二、COM组件互操作

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

4、处理Html DOM对象

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

 

 

dynamic是做为简化互操作性而被MSDN中山大学肆渲染,
我倍感正是依据这点,才被1些开垦人士误解:因为大多开荒职员不会接触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类型实例,见下边包车型客车例子:

接下去1般会冒出如下难点:“既然dynamic对象足以是自由对象并且编写翻译器不会检讨它是何等,那是不是意味你能够传递1个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。3个很好的例证正是COM互操作,那便是为啥它要修改以使用新dynamic特性(越来越多消息点那里“how-to”.aspx))。

如若调用二个方法是传递了dynamic类型的目的,也许被调用的目的是dynamic类型的,那么重载的论断是发出在运营时而不是编译时。

还要,用dynamic关键字和dynamic语言运转时让众多以前不恐怕达成或难以实现的方案变得实惠,包罗与动态语言互操作。笔者在头里的博客里重申过那八个情状: Introducing
ExpandoObject 和Creating
Wrappers with
DynamicObject.

动态语言运行时(dynamic language runtime DL奥迪Q伍)

您或者想去MSDN
walkthrough.aspx)看看,它显示你该怎么从C#和Visual
Basic调用IronPython库,二个当真很酷的牵线,Using Dynamic Languages to
Build Scriptable
Applications,笔者Dino
Viehland。另二个好的介绍呈现一些事例并解释设计标准背后是其一特点Dynamic
Binding in C#
4,作者Mads
Torgersen。

动态语言运营时是.NET Framework 4 Beta
第11中学的一组新的API,它提供了对c#中dynamic类型的援助,也达成了像IronPython和IronRuby之类的动态程序设计语言。

敲定是我们不须求操心会有人能用dynamic天性破坏你的代码。它从未更加多(同时,也从未越来越少)的摇摇欲坠相对于object关键字。

dynamic可以简化反射

之所以,假使您时不时选用object关键字并且只好推行一批示后转载换”并且/或然”使用反射来调用对象的方法或品质,你大概应该注意一下dynamic关键字。在广大时候它比object更便于而且编写更加少的代码。

先前小编们如此使用反射:

原来的书文未有提到var关键字,相信广大人会在那时想到var。

 

var在C#三.0中生出,其在MSDN中的定义:在点子范围中宣称的变量能够具备隐式类型
var。隐式类型的地面变量是强类型变量(就恍如你曾经宣示该品种同样),但由编写翻译器鲜明项目。

威尼斯人线上娱乐 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

 

现在,大家有了简化的写法:

VA昂Cora 是3.5新出的3个定义变量的门类
实际也就是弱化类型的概念
VAKuga可代替任何项目
编写翻译器会遵照上下文来判定你究竟是想用什么品种的

dynamic
dynamicSample2 = new DynamicSample();

至于何以状态下用到VA宝马X3 作者想就是你无法明确本身将用的是哪些项目
就足以使用VA福特Explorer 类似 OBJECT
但是功用比OBJECT高点

int re2

dynamicSample2.Add(1, 2);

咱俩恐怕会对如此的简化不认为然,毕竟看起来代码并未减少多少,但是,假设思考到功效兼美观五个特色,那么dynamic的优势就显现出来了。编写翻译器对dynamic进行了优化,比尚未通过缓存的反射功效快了数不完。如若非要对比,能够将下边两者的代码(调用Add方法有个别)运维一千000就足以得出结论。

选取var定义变量时有以下多个特性:

  1. 非得在概念时初叶化。也正是必须是var s =
    “abcd”方式,而不能够是之类方式:

var s;

s = “abcd”;

  1. 1但初步化达成,就无法再给变量赋与早先化值类型分歧的值了。

  2. var需求是有的变量。

四.
利用var定义变量和object分化,它在功能上和使用强类型格局定义变量完全一致。

 

var代表“变量的档次是在编写翻译时间调控制的”,不过dynamic表示“变量的连串是在运营时间调控制的”。因而,dynamic与var具备完全差别的含义。 

var让你在开端化变量时少输入1些字,编写翻译器会基于右值来揆度出变量的种类。dynamic更决心,它报告编写翻译器,根本就别理终归是什么类型,运营时再揣摸不迟。

var只可以用来局地变量的定义,你无法把类的品质定义成
var,也无法把艺术的归来值类型或许是参数类型定义成var。dynamic就未有这几个局限了。

dynamic类型并从未跳过类型校验,只是延迟到了运行时。假设在运维时,检查测试到品种不包容,照样会抛出相当。

您只怕在偏下情况下接纳dynamic:

1.COM对象

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

叁.反光对象

4.C# 4.0中动态创立的对象


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图