什么时候应该在c#4.0中使用动态关键字?

什么时候应该在c#4.0中使用动态关键字?,c#,dynamic,c#-4.0,keyword,C#,Dynamic,C# 4.0,Keyword,什么时候应该在c#4.0中使用动态关键字?……有没有在c#4.0中使用动态关键字的好例子来解释它的用法 只有在不使用Dynamic时才应使用,因为它很痛苦。就像微软办公图书馆一样。在所有其他情况下都应该避免,因为编译类型检查是有益的。下面是使用dynamic的好情况 从Silverlight调用javascript方法 COM互操作 可能在不创建自定义类的情况下读取Xml、Json 这个怎么样?这是我一直在寻找的东西,我想知道为什么没有“动态”很难做到 interface ISomeData {

什么时候应该在c#4.0中使用动态关键字?……有没有在c#4.0中使用动态关键字的好例子来解释它的用法

只有在不使用Dynamic时才应使用,因为它很痛苦。就像微软办公图书馆一样。在所有其他情况下都应该避免,因为编译类型检查是有益的。下面是使用dynamic的好情况

  • 从Silverlight调用javascript方法
  • COM互操作
  • 可能在不创建自定义类的情况下读取Xml、Json
    这个怎么样?这是我一直在寻找的东西,我想知道为什么没有“动态”很难做到

    interface ISomeData {}
    class SomeActualData : ISomeData {}
    class SomeOtherData : ISomeData {}
    
    interface ISomeInterface
    {
        void DoSomething(ISomeData data);
    }
    
    class SomeImplementation : ISomeInterface
    {
        public void DoSomething(ISomeData data)
        {
            dynamic specificData = data;
            HandleThis( specificData );
        }
        private void HandleThis(SomeActualData data)
        { /* ... */ }
        private void HandleThis(SomeOtherData data)
        { /* ... */ }
    
    }
    
    如果没有采用具体类型的重载方法,则可能需要捕获运行时异常并处理所需的方式

    不使用
    动态
    的等效值为:

        public void DoSomething(ISomeData data)
        {
            if(data is SomeActualData)
              HandleThis( (SomeActualData) data);
            else if(data is SomeOtherData)
              HandleThis( (SomeOtherData) data);
            ...
            else
             throw new SomeRuntimeException();
        }
    
    其中谈到了c#中的动态关键字。要点如下:

    dynamic关键字确实很强大,当与动态语言一起使用时,它是不可替代的,但在设计静态类型对象根本无法使用的代码时,它也可以用于棘手的情况

    考虑一下缺点:

  • 没有编译时类型检查,这意味着除非您对单元测试(cough)有100%的信心,否则您将面临风险

  • 由于额外的运行时开销,dynamic关键字比老式的静态类型代码使用更多的CPU周期,如果性能对项目很重要(通常是这样),请不要使用dynamic

  • 常见错误包括在公共方法中返回包装在dynamic关键字中的匿名类型。匿名类型是特定于程序集的,跨程序集返回它们(通过公共方法)将抛出错误,即使简单的测试会发现这一点,但您现在有了一个只能从特定位置使用的公共方法,这就是糟糕的设计

  • 这是一个滑坡,没有经验的开发人员渴望写一些新的东西,并尽力避免使用更多的类(这并不一定局限于没有经验的开发人员),如果他们在代码中看到动态,他们将越来越多地使用动态,通常我会在代码审查中对动态/添加动态进行代码分析检查

  • 如dynamics中所述,设计糟糕的外部库会更易于使用:Microsoft提供了Microsoft.Office.Interop.Excel程序集的示例。 使用dynamic,您可以在使用此程序集时避免许多恼人的显式强制转换

    另外,与@user2415376相反,它绝对不是处理接口的方法,因为我们从语言的开始就已经实现了多态性
    你可以用

      ISomeData specificData = data;
    
    而不是

    dynamic specificData = data;
    

    另外,它将确保您不会传递错误类型的数据对象。

    在所有可以使用动态的情况下使用动态绝对不是一个好主意。这是因为您的程序将失去编译时检查的好处,而且速度也会慢得多。

    我想复制一篇代码项目文章的摘录,其中定义:

    为什么使用动态?

    在静态类型的世界中,动态为开发人员提供了很多约束 上吊。处理类型可以为的对象时 在编译时已知,您应该避免使用dynamic关键字 成本。早些时候,我说我最初的反应是否定的,那又怎样 我改变主意了?引用玛格丽特·阿特伍德的话,环境就是一切。什么时候 静态输入,动态输入毫无意义。如果你是 处理未知或动态类型时,通常需要 通过反思与它沟通。反射式代码不容易实现 读取,并具有上述动态类型的所有缺陷。在这个 上下文、动态很有意义。[更多]

    而动态关键字的一些特点是:

  • 动态类型化-这意味着声明的变量类型为 由编译器在运行时决定
  • 无需在声明时初始化
  • e、 g

  • 在运行时捕获错误

  • Intellisense不可用,因为只能在运行时知道类型及其相关方法和属性。[


  • 下面是最近的一个案例,其中使用
    动态
    是一个简单的解决方案

    我已经将一些代码从VB6移植到C#。这些移植的代码仍然需要通过COM互操作调用VB6对象上的其他方法

    需要调用的类如下所示:

    class A
    {
        void Foo() {...}
    }
    
    class B
    {
        void Foo() {...}
    }
    
    // Obj must be either an A or a B 
    void Bar(dynamic Obj) 
    {
        Obj.Foo();
    }
    
    (也就是说,这就是VB6类在C#中通过COM互操作查看的方式;特别是自动生成的COM可调用包装器)

    由于A和B是相互独立的,所以不能将一个强制转换为另一个,并且它们没有公共基类(COM不支持AFAIK和VB6当然不支持的基类。而且它们没有实现公共接口-见下文)

    移植的原始VB6代码执行以下操作:

    “Obj必须是A或B
    子栏(对象为Obj)
    调用Obj.Foo()
    端接头
    
    现在在VB6中,您可以将对象作为
    Object
    传递,运行时将确定这些对象是否具有方法
    Foo()
    。但在C中,直译是:

    // Obj must be either an A or a B 
    void Bar(object Obj) 
    {
        Obj.Foo();
    }
    
    它不会编译,因为
    对象
    没有一个名为“Foo”的方法,而C#是类型安全的将不允许这样做

    因此,简单的“修复”是使用
    动态
    ,如下所示:

    class A
    {
        void Foo() {...}
    }
    
    class B
    {
        void Foo() {...}
    }
    
    // Obj must be either an A or a B 
    void Bar(dynamic Obj) 
    {
        Obj.Foo();
    }
    
    这会将类型安全性推迟到运行时,但假设您已经正确地完成了这项工作,就可以了

    对于新的代码,我不赞成这样做,但在这种情况下(从这里的其他答案来看,我认为这并不少见),它是有价值的

    考虑的备选方案:

    • 使用反射调用Foo()。可能会起作用,但需要更多的努力,可读性较差

    • 修改t