简体   繁体   English

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

[英]When should one use dynamic keyword in c# 4.0?

什么时候应该在c#4.0中使用动态关键字?....... c#4.0中有动态关键字的任何好例子都解释了它的用法....

Dynamic should be used only when not using it is painful . 在不使用动态时才应使用动态是痛苦的 Like in MS Office libraries. 就像在MS Office库中一样。 In all other cases it should be avoided as compile type checking is beneficial. 在所有其他情况下,应该避免它,因为编译类型检查是有益的。 Following are the good situation of using dynamic. 以下是使用动态的好情况。

  1. Calling javascript method from Silverlight. 从Silverlight调用javascript方法。
  2. COM interop. COM互操作。
  3. Maybe reading Xml, Json without creating custom classes. 也许在不创建自定义类的情况下阅读Xml,Json。

How about this? 这个怎么样? Something I've been looking for and was wondering why it was so hard to do without 'dynamic'. 我一直在寻找的东西,并想知道为什么没有“动态”这么难。

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)
    { /* ... */ }

}

You just have to maybe catch for the Runtime exception and handle how you want if you do not have an overloaded method that takes the concrete type. 如果没有采用具体类型的重载方法,您只需要捕获Runtime异常并处理您想要的方法。

Equivalent of not using dynamic will be: 相当于不使用dynamic将是:

    public void DoSomething(ISomeData data)
    {
        if(data is SomeActualData)
          HandleThis( (SomeActualData) data);
        else if(data is SomeOtherData)
          HandleThis( (SomeOtherData) data);
        ...
        else
         throw new SomeRuntimeException();
    }

As described in here dynamics can make poorly-designed external libraries easier to use: Microsoft provides the example of the Microsoft.Office.Interop.Excel assembly. 作为描述这里的动态可以使设计拙劣的外部库更容易使用:微软提供的Microsoft.Office.Interop.Excel组件的例子。 And With dynamic, you can avoid a lot of annoying, explicit casting when using this assembly. 使用动态,您可以在使用此程序集时避免大量烦人的显式转换。

Also, In opposition to @user2415376 ,It is definitely not a way to handle Interfaces since we already have Polymorphism implemented from the beginning days of the language! 另外,与@ user2415376相反,它绝对不是一种处理接口的方法,因为我们已经从语言的开头几天实现了多态性!
You can use 您可以使用

  ISomeData specificData = data;

instead of 代替

dynamic specificData = data;

Plus it will make sure that you do not pass a wrong type of data object instead. 此外,它将确保您不会传递错误类型的数据对象。

Check this blog post which talks about dynamic keywords in c#. 查看此博客文章 ,其中讨论了c#中的动态关键字。 Here is the gist: 这是要点:

The dynamic keyword is powerful indeed, it is irreplaceable when used with dynamic languages but can also be used for tricky situations while designing code where a statically typed object simply will not do. 动态关键字确实很强大,当与动态语言一起使用时它是不可替代的,但在设计静态类型对象根本不会做的代码时也可以用于棘手的情况。

Consider the drawbacks: 考虑一下缺点:

  1. There is no compile-time type checking, this means that unless you have 100% confidence in your unit tests (cough) you are running a risk. 没有编译时类型检查,这意味着除非您对单元测试(咳嗽)有100%的信心,否则您将面临风险。

  2. The dynamic keyword uses more CPU cycles than your old fashioned statically typed code due to the additional runtime overhead, if performance is important to your project (it normally is) don't use dynamic. 由于额外的运行时开销,动态关键字比旧式静态类型代码使用更多的CPU周期,如果性能对您的项目很重要(通常是)不使用动态。

  3. Common mistakes include returning anonymous types wrapped in the dynamic keyword in public methods. 常见错误包括返回公共方法中包含在dynamic关键字中的匿名类型。 Anonymous types are specific to an assembly, returning them across assembly (via the public methods) will throw an error, even though simple testing will catch this, you now have a public method which you can use only from specific places and that's just bad design. 匿名类型特定于程序集,通过程序集返回它们(通过公共方法)将引发错误,即使简单的测试会捕获这个,你现在有一个公共方法,你只能从特定的地方使用,这只是糟糕的设计。

  4. It's a slippery slope, inexperienced developers itching to write something new and trying their best to avoid more classes (this is not necessarily limited to the inexperienced) will start using dynamic more and more if they see it in code, usually I would do a code analysis check for dynamic / add it in code review. 这是一个滑坡,缺乏经验的开发人员渴望写一些新的东西,并尽力避免更多的课程(这不一定限于缺乏经验)将开始使用动态越来越多,如果他们在代码中看到它,通常我会做一个代码分析检查动态/在代码审查中添加它。

It is definitely a bad idea to use dynamic in all cases where it can be used. 在可以使用动态的所有情况下使用动态绝对是个坏主意。 This is because your programs will lose the benefits of compile-time checking and they will also be much slower. 这是因为您的程序将失去编译时检查的好处,而且它们也会慢得多。

I will like to copy an excerpt from the code project post, which define that : 我想复制一下代码项目帖子的摘录,它定义了:

Why use dynamic? 为何使用动态?

In the statically typed world, dynamic gives developers a lot of rope to hang themselves with. 在静态类型的世界中,动态为开发人员提供了很多可以自行处理的绳索。 When dealing with objects whose types can be known at compile time, you should avoid the dynamic keyword at all costs. 处理在编译时可以知道类型的对象时,应该不惜一切代价避免使用dynamic关键字。 Earlier, I said that my initial reaction was negative, so what changed my mind? 早些时候,我说我最初的反应是消极的,所以改变了我的想法? To quote Margret Attwood, context is all. 引用Margret Attwood的话,背景就是全部。 When statically typing, dynamic doesn't make a stitch of sense. 静态打字时,动态不会形成一种感觉。 If you are dealing with an unknown or dynamic type, it is often necessary to communicate with it through Reflection. 如果您正在处理未知或动态类型,通常需要通过Reflection与其进行通信。 Reflective code is not easy to read, and has all the pitfalls of the dynamic type above. 反射代码不易阅读,并且具有上述动态类型的所有缺陷。 In this context, dynamic makes a lot of sense.[More] 在这种情况下,动态很有意义。[更多]

While Some of the characteristics of Dynamic keyword are: 虽然Dynamic关键字的一些特征是:

  1. Dynamically typed - This means the type of variable declared is decided by the compiler at runtime time. 动态类型 - 这意味着声明的变量类型由编译器在运行时决定。
  2. No need to initialize at the time of declaration. 无需在声明时初始化。

eg, 例如,

dynamic str; 

str=”I am a string”; //Works fine and compiles

str=2; //Works fine and compiles
  1. Errors are caught at runtime 错误在运行时捕获

  2. Intellisense is not available since the type and its related methods and properties can be known at run time only. Intellisense不可用,因为类型及其相关方法和属性只能在运行时知道。 [ https://www.codeproject.com/Tips/460614/Difference-between-var-and-dynamic-in-Csharp] [ https://www.codeproject.com/Tips/460614/Difference-between-var-and-dynamic-in-Csharp]

Here is a recent case in which using dynamic was a straightforward solution. 这是最近的一个案例,其中使用dynamic是一个简单的解决方案。

I had ported some code from VB6 into C#. 我已经将VB6中的一些代码移植到C#中。 This ported code still needed to call other methods on VB6 objects via COM interop. 这个移植代码仍然需要通过COM互操作调用VB6对象上的其他方法。

The classes needing to be called looked like this: 需要调用的类看起来像这样:

class A
{
    void Foo() {...}
}

class B
{
    void Foo() {...}
}

(ie, this would be the way the VB6 classes looked in C# via the COM interop; specifically the COM-callable wrapper which was autogenerated). (也就是说,这将是VB6类通过COM互操作在C#中查看的方式;特别是自动生成的COM可调用包装器)。

Since A and B are independent of each other you can't cast one to the other, and they have no common base class (COM doesn't support that AFAIK and VB6 certainly didn't. And they did not implement a common interface - see below). 由于A和B是彼此独立的,你不能将它们互相转换,并且它们没有共同的基类(COM不支持AFAIK和VB6当然没有。而且它们没有实现通用接口 - 见下文)。

The original VB6 code which was ported did this: 移植的原始VB6代码执行了此操作:

' Obj must be either an A or a B 
Sub Bar(Obj As Object) 
    Call Obj.Foo()
End Sub

Now in VB6 you can pass things around as Object and the runtime will figure out if those objects have method Foo() or not. 现在在VB6中,您可以将Object作为Object传递,运行时将确定这些对象是否具有方法Foo() But in C# a literal translation would be: 但在C#中,字面翻译将是:

// Obj must be either an A or a B 
void Bar(object Obj) 
{
    Obj.Foo();
}

Which will NOT work. 哪个不行。 It won't compile because object does not have a method called "Foo", and C# being typesafe won't allow this. 它不会编译,因为object没有名为“Foo”的方法,并且C#为typesafe不允许这样做。

So the simple "fix" was to use dynamic , like this: 所以简单的“修复”是使用dynamic ,如下所示:

// Obj must be either an A or a B 
void Bar(dynamic Obj) 
{
    Obj.Foo();
}

This defers type safety until runtime, but assuming you've done it right works just fine. 这将类型安全推迟到运行时间,但假设你已经完成它正常工作就好了。

I wouldn't endorse this for new code, but in this situation (which I think is not uncommon judging from other answers here) it was valuable. 我不赞同这个新代码,但在这种情况下(我认为从这里的其他答案判断并不罕见)它很有价值。

Alternatives considered: 考虑的替代方案:

  • Using reflection to call Foo(). 使用反射来调用Foo()。 Probably would work, but more effort and less readable. 可能会工作,但更多的努力和更少的可读性。

  • Modifying the VB6 library wasn't on the table here, but maybe there could be an approach to define A and B in terms of a common interface, which VB6 and COM would support. 这里没有修改VB6库,但可能有一种方法可以根据VB6和COM支持的通用接口来定义A和B. But using dynamic was much easier. 但使用动态更容易。


Note: This probably will turn out to be a temporary solution. 注意:这可能会成为一个临时解决方案。 Eventually if the remaining VB6 code is ported over then a proper class structure can be used and static compile time checking would replace the use of dynamic . 最终,如果剩下的VB6代码被移植,那么可以使用正确的类结构,静态编译时检查将取代dynamic的使用。 I admit that such a hopeful future made me more comfortable using this approach which could have some maintenance risk. 我承认,这样一个充满希望的未来使我更习惯使用这种可能存在一些维护风险的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM