在C#中使用动态类型的缺点


14

我最近一直在研究C#中的动态类型。通过一些示例,我理解代码一旦编译,就无需再次重新编译,而是可以直接执行。

我觉得关键字提供的灵活性实际上可以随意更改数据类型是一个很大的优势

题,

除了错误的动态方法调用之外,是否存在任何其他特定缺陷,这些错误会引发开发人员在开始执行之前必须知道的运行时异常。


3
在C#3中,我一直认为使用object直接类型转换是一种代码嗅觉。在几乎每种情况下,这都意味着我或我的团队中的一个没有为此功能设计适当的接口。我猜想,如果我现在正在使用C#4,我也会对使用C#感到几乎相同dynamic。如果您使所有内容都具有动态性,那么我可以看到这种情况,但是在那种情况下,您最好首先选择一种动态类型化的语言。* 8')
Mark Booth

@MarkBooth +1为视角。那么可以肯定地说,尽管在4.0中引入了动态类型,但使用C#的核心实现仍将保持强类型化
Karthik Sreenivasan 2012年

dynamic在C#中使用意味着,如果您需要的只是一小部分代码的动态键入,则不必退出IronPython。对于一个表达式评估器,我已经非常成功地使用它dynamic来表示表达式的操作数和评估结果。
Ed James

@EdJames-听起来像是一个很好的用法dynamic,再加上我希望我在使用.Net开发时对IronPython有所了解-它可能使某些我们想做的事情变得容易得多
Mark Booth

Answers:


16

主要缺点是您放弃了C#的主要属性(不一定是优点)之一-它是静态类型的(并且大多数情况下是安全的)。

动态类型化的问题在于它通常会隐藏在编译过程中否则会发现的错误。这样的错误仅在运行时出现,这当然使检测起来更加困难。

IMO很少有理由在C#中使用动态类型,主要的原因是与动态类型的语言进行协作(这是AFAIK,首先引入了动态的原因)。

如果要进行完全动态类型的编程,则应查看设计为动态的某种语言,而不是将C#编程为动态的。如果要使用.Net库,则可以使用例如IronPython


IronPython +1。这意味着从长远来看,这可能会导致维护问题。
Karthik Sreenivasan'2

6
dynamic给您带来的最大好处就是能够将对象上载到其实际类型,而无需任何形式的反射。例如,如果Base foo = new Derived();有两个重载方法Moo(Base x)Moo(Derived x),然后Moo(foo)调用Moo(Base x),而是Moo((dynamic)foo)调用Moo(Derived x)。这样就可以很好地实现Visitor模式的实现,例如:code.logos.com/blog/2010/03/…,并且通常是一种非常强大的技术。

@TheMouthofaCow尼斯,当然,动态还有其他一些“合法的”用法,但是它们之间相差无几(在尝试这样的事情之前,您一定要知道自己在做什么)。
马捷Zábský

@TheMouthofaCow注意一个相对较新的设计模式(“访客模式”)。谢谢。
Karthik Sreenivasan '02

1
是的,这很酷。上周我独立提出了它,因此很高兴看到它已被C#军械库采用。

9

我不确定您要寻找的缺点是什么,但是如果您想了解可用于静态类型而不是可用于静态类型的功能,dynamic则几乎没有:

  1. 扩展方法不起作用。这可能是最大的。如果有的话dynamic collection,就不能使用像这样的代码collection.Distinct()。这是因为可用的扩展方法取决于命名空间using,而DLR无法知道它们。

    解决方法是,您可以像调用普通静态方法一样调用该方法Enumerable.Distinct(collection)。或者,您可以将集合的类型更改为IEnumerable<dynamic>

  2. foreach要求IEnumerable。在正常的C#中,foreach是基于模式的。也就是说,它不需要任何特定的接口,只需一个GetEnumerator()返回合适对象的方法。如果使用foreachon dynamicIEnumerable则必须实现。但是由于这种行为的原因是C#1.0没有泛型,所以这种“缺点”几乎是无关紧要的。


+1为扩展方法。这是否也适用于其他LINQ查询运算符,例如GroupBy()?
Karthik Sreenivasan '02

2
@Karthik:是的。我认为扩展方法是编译时语法糖,因此它们没有得到解决的事实。

@TheMouthofaCow +1-感谢您的澄清。
Karthik Sreenivasan '02

1
我同意扩展方法,即动态方法如何在运行时无法找出扩展方法,但我无法遵循您所解释的动态集合。
Karthik Sreenivasan '02

7

.net中的动态类型(不是声明为动态的变量)的问题在于它们没有大量可用于静态类型的功能。

  • 没有思考(您可以遍历成员,但不能太多)
  • 没有元数据(在动态数据站点/ mvc中进行验证)
  • 绝对在编译时不检查(不会发现任何拼写错误)
  • 由于这是一个强大的功能,菜鸟可能会倾向于滥用/滥用/误解它
  • 用动态类型编写的代码往往难以维护且难以重构
  • 由于鸭类打字和其他功能,大师可能会编写其他人无法读取的代码

因此,除非您知道自己在做什么,否则不要使用动态类型编写代码。


6

因为dynamic只是一个标记,object所以它包装了值类型。

这可能会影响性能,但是由于无论如何我都会在性能关键的代码中使用静态类型,因此实际上这不是问题。

此装箱也干扰可变值类型。如果使用修改它们dynamic,则只能修改装箱的副本。但是由于一开始就不应使用可变值类型,所以这也不是大问题。


+1我绝对同意。对于性能至关重要的代码,静态类型将是最好的方法。
Karthik Sreenivasan '02
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.