什么时候应该在c#4.0中使用动态关键字?....... c#4.0中有动态关键字的任何好例子都解释了它的用法......
答案 0 :(得分:36)
动态应该只用不使用时很痛苦。就像在MS Office库中一样。在所有其他情况下,应该避免它,因为编译类型检查是有益的。以下是使用动态的好情况。
答案 1 :(得分:11)
这个怎么样?我一直在寻找的东西,并且想知道为什么没有“动态”这么难以做到。
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)
{ /* ... */ }
}
如果你没有采用具体类型的重载方法,你只需捕获Runtime异常并处理你想要的方式。
不使用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();
}
答案 2 :(得分:6)
如here中所述,动态可以使设计不佳的外部库更易于使用:Microsoft提供了Microsoft.Office.Interop.Excel程序集的示例。 使用动态,你可以在使用这个程序集时避免很多恼人的显式转换。
另外,与@ user2415376相反,它绝对不是一种处理接口的方法,因为我们已经从语言的开头就实现了多态性!
你可以使用
ISomeData specificData = data;
而不是
dynamic specificData = data;
另外,它会确保您不会传递错误类型的数据对象。
答案 3 :(得分:3)
Check this blog post讨论c#中的动态关键字。这是要点:
动态关键字确实很强大,它在与动态语言一起使用时是不可替代的,但在设计静态类型对象根本不会执行的代码时也可用于棘手的情况。
考虑缺点:
没有编译时类型检查,这意味着除非您对单元测试(咳嗽)有100%的信心,否则您将面临风险。
由于额外的运行时开销,动态关键字使用的CPU周期比旧式静态类型代码多,如果性能对项目很重要(通常是)不使用动态。
< / LI>常见错误包括返回公共方法中包含在dynamic关键字中的匿名类型。匿名类型特定于程序集,通过程序集返回它们(通过公共方法)将引发错误,即使简单的测试会捕获这个,你现在有一个公共方法,你只能从特定的地方使用,这只是糟糕的设计
这是一个滑坡,缺乏经验的开发人员渴望写一些新的东西,并尽力避免更多的课程(这不一定限于缺乏经验)将开始使用动态越来越多,如果他们在代码中看到它,通常我会做代码分析检查动态/在代码审查中添加它。
答案 4 :(得分:1)
在可以使用动态的所有情况下使用动态绝对是个坏主意。这是因为你的程序将失去编译时检查的好处,而且它们也会慢得多。
答案 5 :(得分:1)
我想从代码项目帖子中复制一段摘录,其中定义了:
为什么要使用动态?
在静态类型的世界中,动态为开发人员提供了很多支持 自嘲。处理类型可以的对象时 在编译时已知,你应该完全避免使用dynamic关键字 成本。早些时候,我说我最初的反应是否定的,那是什么 改变主意?引用Margret Attwood的话,背景就是全部。什么时候 静态打字,动态并没有形成一种感觉。如果你是 处理未知或动态类型时,通常需要 通过反思与它沟通。反光代码并不容易 阅读,并具有上述动态类型的所有陷阱。在这 上下文,动态很有意义。[更多]
虽然Dynamic关键字的一些特征是:
如,
dynamic str;
str=”I am a string”; //Works fine and compiles
str=2; //Works fine and compiles
在运行时捕获错误
智能感知不可用,因为类型及其相关方法和属性只能在运行时知道。 [https://www.codeproject.com/Tips/460614/Difference-between-var-and-dynamic-in-Csharp]
答案 6 :(得分:0)
以下是最近使用dynamic
作为简单解决方案的案例。
我已将VB6中的一些代码移植到C#中。这个移植代码仍然需要通过COM互操作调用VB6对象上的其他方法。
需要调用的类看起来像这样:
class A
{
void Foo() {...}
}
class B
{
void Foo() {...}
}
(即,这将是VB6类通过COM互操作在C#中查看的方式;特别是自动生成的COM可调用包装器。)
由于A和B是彼此独立的,你不能将它们互相转换,并且它们没有共同的基类(COM不支持AFAIK和VB6当然没有。并且它们没有实现通用界面 - 见下文)。
移植的原始VB6代码执行了此操作:
' Obj must be either an A or a B
Sub Bar(Obj As Object)
Call Obj.Foo()
End Sub
现在在VB6中,您可以将事物传递为Object
,运行时将确定这些对象是否具有方法Foo()
。但在C#中,字面翻译将是:
// Obj must be either an A or a B
void Bar(object Obj)
{
Obj.Foo();
}
哪个不行。它不会编译,因为object
没有名为“Foo”的方法,而C#属于类型安全将不允许这样做。
所以简单的“修复”是使用dynamic
,如下所示:
// Obj must be either an A or a B
void Bar(dynamic Obj)
{
Obj.Foo();
}
这会延迟到运行时的类型安全性,但假设你已经完成了它就可以了。
我不赞同这个新代码,但在这种情况下(我认为从这里的其他答案判断并不罕见)它很有价值。
考虑的替代方案:
使用反射来调用Foo()。可能会起作用,但更多的努力和更少的可读性。
这里没有修改VB6库,但是可能有一种方法可以根据VB6和COM支持的通用接口来定义A和B.但使用动态更容易。
注意:这可能会成为一种临时解决方案。最终,如果剩下的VB6代码被移植,那么可以使用适当的类结构,静态编译时检查将取代dynamic
的使用。我承认,这样一个充满希望的未来使我更习惯使用这种可能存在一些维护风险的方法。