【问题标题】:Does the C# 4.0 "dynamic" keyword make Generics redundant?C# 4.0“动态”关键字是否使泛型变得多余?
【发布时间】:2010-10-24 02:52:33
【问题描述】:

我对 C# (C#4 dynamic keyword - why not?) 中的动态特性感到非常兴奋,尤其是因为在我的代码的某些库部分中我使用了很多反射。

我的问题有两个:

1. “动态”是否会取代泛型,如下例所示?

泛型方法:

public static void Do_Something_If_Object_Not_Null<SomeType>(SomeType ObjToTest) {
        
        //test object is not null, regardless of its Type
        if (!EqualityComparer<SomeType>.Default.Equals(ObjToTest, default(SomeType))) {
            //do something
        }
    }

动态方法(??):

public static void Do_Something_If_Object_Not_Null(dynamic ObjToTest) {

        //test object is not null, regardless of its Type?? but how?
        if (ObjToTest != null) {
            //do something
        }
    }

2。 “动态”现在是否允许方法返回匿名类型,如下例所示?:

 public static List<dynamic> ReturnAnonymousType() {
        return MyDataContext.SomeEntities.Entity.Select(e => e.Property1, e.Property2).ToList();
    }

酷,干杯

编辑:

仔细考虑我的问题,并根据答案,我发现我完全搞砸了主要的通用/动态问题。它们确实是完全不同的。是的,感谢您提供的所有信息。

第 2 点呢?

【问题讨论】:

    标签: c# .net generics reflection dynamic


    【解决方案1】:

    dynamic 可能会简化有限数量的反射场景(您预先知道成员名称,但没有接口) - 特别是,它可能有助于通用运算符 (although other answers exist) - 但除了泛型运算符的技巧,与泛型几乎没有交叉。

    泛型允许您(在编译时)了解您正在使用的类型 - 相反,dynamic关心类型。 特别是 - 泛型允许您指定和证明许多条件关于一个类型 - 即它可能实现一些接口,或具有公共无参数构造函数。 dynamic 也无济于事:它不支持接口,而且比简单地不关心接口更糟糕的是,这意味着我们甚至无法看到dynamic 的显式接口实现。

    另外,dynamic 确实是object 的一个特例,所以拳击开始发挥作用,但带有报复性。

    实际上,您应该将dynamic 的使用限制在几种情况:

    • COM 互操作
    • DLR 互操作
    • 也许一些轻松的鸭子打字
    • 也许一些通用运算符

    对于所有其他情况,泛型和常规 C# 都是可行的方法。

    【讨论】:

    • 动态的另一个令人惊讶的有用用途:在 RESTful Web 情况下的 JSON 互操作——尤其是当所讨论的 JSON 在不同调用之间波动很大时。有一些库可以对动态对象序列化和反序列化 JSON。
    【解决方案2】:

    回答你的问题。 没有。

    • 泛型为您提供“算法重用” - 您可以编写独立于数据类型的代码。动态关键字不做任何与此相关的事情。我定义了List&lt;T&gt;,然后我可以将它用于字符串、整数等列表...
    • 类型安全:整个编译时检查辩论。动态变量不会以编译时警告/错误提醒您,以防您出错,如果您尝试调用的方法丢失,它们只会在运行时爆炸。静态与动态类型之争
    • 性能:泛型将使用值类型的算法/代码的性能提高了一个显着的数量级。它可以防止花费我们 pre-Generics 的整个装箱-拆箱周期。 Dynamic 对此也无能为力。

    dynamic 关键字会给你什么

    • 更简单的代码(当您与 Excel 互操作时,可以说..)您不需要指定类或对象模型的名称。如果您调用正确的方法,则运行时将负责调用该方法(如果该方法当时存在于对象中)。即使未定义该方法,编译器也会让您摆脱困境。然而,这意味着这将比进行编译器验证/静态类型的方法调用要慢,因为 CLR 必须在调用动态 var 字段/方法之前执行检查。
    • 动态变量可以在不同的时间点保存不同类型的对象 - 您不受特定系列或对象类型的限制。

    【讨论】:

    • 感谢 Gishu,很好的回答。你和马克之间的比例是 50/50。所以真的应该允许不止一个答案吗?...去想一想。再次感谢
    【解决方案3】:

    为了回答您的第一个问题,泛型在编译时解析,动态类型在运行时解析。所以在类型安全和速度上是有一定区别的。

    【讨论】:

    • 为了完整起见,.NET 中的泛型由运行时提供,如果需要,您可以在运行时指定泛型类型参数。
    • @Peter:谢谢彼得。我在实施方面考虑得更多。虽然我现在看到实际上使用“动态”而不是泛型,作为我的例子,有点像使用对象
    【解决方案4】:

    动态类和泛型是完全不同的概念。使用泛型,您可以在编译时定义类型。它们不会改变,它们不是动态的。您只需在某个类或方法上放置一个“占位符”,以使调用代码定义类型。

    动态方法是在运行时定义的。你那里没有编译时类型安全。动态类类似于您有对象引用并使用反射通过其字符串名称调用方法。

    【讨论】:

      【解决方案5】:

      回答第二个问题:在 C# 3.0 中可以返回匿名类型。将类型转换为对象,返回它并使用反射来访问它的成员。动态关键字只是语法糖。

      【讨论】:

      • 谢谢尼基。那么,在 C#4.0 中,我可以返回动态而不是对象,然后不必使用反射吗?
      • 是的,你可以。使用动态作为返回匿名类型的方法的返回类型。然后您可以在不使用反射的情况下访问成员。
      猜你喜欢
      • 1970-01-01
      • 2010-09-22
      • 2011-05-08
      • 2010-10-01
      • 2022-01-03
      • 1970-01-01
      • 2021-10-19
      • 2018-10-01
      • 1970-01-01
      相关资源
      最近更新 更多