zoukankan      html  css  js  c++  java
  • 理解C# 4 dynamic(1)

    阅读目录:

    一. 为什么是它们三个

    二. 能够任意赋值的原因

    三. dynamic的用法

    四. 使用dynamic的注意事项

    一. 为什么是它们三个?

    拿这三者比较的原因是它们在使用的时候非常相似。你可以用它们声明的变量赋任何类型的值。

    看看下面的示例:

    var a = 1;
    object b = 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++;

    三. dynamic的用法

    1 直接使用该类型,可以非常方便的插入属性, 方法

    static void Main(string[] args)
    {
        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();
    }

    枚举所有成员

    foreach (var property in (IDictionary<String, Object>)dynEO)
    {
         Console.WriteLine(property.Key + ": " + property.Value);
    }

    3 简化反射

    常用的处理反射的例子:

    object calc = GetCalculator();
    Type calcType = calc.GetType();
    object res = calcType.InvokeMember( "Add", BindingFlags.InvokeMethod, null, new object[] { 10, 20 });
    int sum = Convert.ToInt32(res);

    使用dynamic之后:

     dynamic calc = GetCalculator();
     int sum = calc.Add(10, 20);

    四,使用dynamic的注意事项

    有了dynamic,.net就以及有了动态类型的优势,但是由于对于dynamic类型的所有操作,都是在运行时确定的,所有错误无法在编译时候出现,使用的时候,就需要非常小心。

    因为dynamic是类型,所以如果函数接受的是确定类型的参数,是不能传入dynamic类型的,这样会有编译错误。比如:

    public int Add(int a, int b){
        return a + b;
    }
    dynamic test1 = 1;
    dynamic test2 = 2;
    Add(test1, test2);

    下面是对上面的例子的修正,谢谢Alan@Net. 大家可以实验一下

      1. #15楼 Alan@Net   2014-02-04 21:30
        为什么我copy你最后一个例子,并没有报错?
      2. #16楼[楼主] JustRun   2014-02-07 08:30
        @Alan@Net
        应该是编译不通过,我待会试试
      3. #17楼[楼主] JustRun   2014-02-08 08:29
        @Alan@Net
        是不会报错,对于普通的类型,int这样的,不会有问题。
        但是如果是对象类型,运行时会报错。

    另外,在我们自己在写函数时,最好不要将dynamic类型作为函数的参数,这就像是使用object作为函数参数一样,会为程序的维护带来后续的麻烦。

    没有人能够确定使用者传入的是什么,而且编译时候不会有问题。如果错误出现在运行时,就有可能是灾难。

  • 相关阅读:
    Effective C# Item6:明辨值类型和引用类型的使用场合
    Effective C# Item15:利用using和try/finally语句来清理资源
    Effective C# Item12:变量初始化器优于赋值语句
    Effective C# Item19:定义并实现接口优于继承类型
    Effective C# Item14:利用构造器链
    Effective C# Item18:实现标准Dispose模式
    Effective C# Item17:尽量减少装箱和拆箱
    Effective C# Item7:将值类型尽可能实现为具有常量性和原子性的类型
    Effective C# Item10:理解GetHashCode()方法的缺陷
    Effective C# Item20:明辨接口实现和虚方法重写
  • 原文地址:https://www.cnblogs.com/JustRun1983/p/3163350.html
Copyright © 2011-2022 走看看