C# 动态语言。运行时与反射

C# 动态语言。运行时与反射,c#,dynamic,reflection,dynamic-language-runtime,C#,Dynamic,Reflection,Dynamic Language Runtime,我计划在我的新项目中使用dynamic关键字。但在开始之前,我想了解一下在反射上使用动态关键字的利弊 以下是关于动态关键字的优点: 可读\可维护的代码 更少的代码行 当我听到与使用dynamic关键字相关的负面消息时,我听到的是: 影响应用程序性能 Dynamic关键字在内部是反射的包装器 动态类型可能会成为难以发现的bug的滋生地 影响与以前.NET版本的互操作性 请帮助我了解我遇到的利弊是否合理?在大多数情况下,使用dynamic关键字不会导致代码明显缩短。在某些情况下,它会;这取决

我计划在我的新项目中使用dynamic关键字。但在开始之前,我想了解一下在反射上使用动态关键字的利弊

以下是关于动态关键字的优点:

  • 可读\可维护的代码
  • 更少的代码行
当我听到与使用dynamic关键字相关的负面消息时,我听到的是:

  • 影响应用程序性能
  • Dynamic关键字在内部是反射的包装器
  • 动态类型可能会成为难以发现的bug的滋生地
  • 影响与以前.NET版本的互操作性

请帮助我了解我遇到的利弊是否合理?

在大多数情况下,使用dynamic关键字不会导致代码明显缩短。在某些情况下,它会;这取决于提供者,因此这是一个重要的区别。您可能永远不应该使用dynamic关键字访问普通CLR对象;好处太小了

dynamic关键字破坏了自动重构工具,使高覆盖率单元测试变得更加重要;毕竟,当您使用编译器时,它不会检查很多东西。当您与一个非常稳定或固有的动态类型API进行互操作时,这并不是一个很大的问题,但是如果您使用关键字dynamic来访问一个API将来可能会更改的库(例如您自己编写的任何代码),则这一问题尤其严重

在有意义的地方,尽量少用关键字,并确保这样的代码有足够的单元测试。不要在不需要它或类型推断(例如,
var
)也可以这样做的地方使用它

编辑:您在下面提到您正在为插件执行此操作。设计时就考虑到了这一点-关键字<代码>动态和反射可能是更好的选择

可读\可维护代码

以我的经验,确实如此

更少的代码行

这并不重要,但会有所帮助

影响应用程序性能

非常轻微。但甚至不接近反射的方式

Dynamic关键字在内部是反射的包装器

完全不真实。dynamic关键字利用动态库运行时

[编辑:根据以下评论进行更正]

动态语言运行时似乎确实使用了反射,而性能的提高只是由于缓存技术

动态类型可能会成为难以发现的bug的滋生地

这可能是真的;这取决于您如何编写代码。您正在有效地从代码中删除编译器检查。如果您的测试覆盖率很好,这可能无关紧要;如果没有,我怀疑你会遇到问题

影响与以前.NET版本的互操作性

不是真的。我的意思是,您将无法针对旧版本编译代码,但是如果您想这样做,那么您应该使用旧版本作为基础并对其进行编译,而不是相反。但是,如果您想使用.NET 2库,则不应该遇到太多问题,只要您在app.config/web.config中包含声明即可


您缺少的一个重要优点是改进了与COM/ATL组件的互操作性。

如果您专门使用dynamic进行反射,您唯一关心的是与以前版本的兼容性。否则,它会胜过反射,因为它可读性更高,篇幅更短。无论如何,如果使用反射,您将失去强大的键入功能和(某些)性能。

在我看来,在使用反射时,除了与旧.NET版本的互操作性之外,您使用动态的所有缺点都存在:

影响应用程序性能

虽然它确实会影响性能,但使用反射也会影响性能。根据我的记忆,DLR在您第一次访问给定类型的动态对象的方法/属性时或多或少地使用反射,并缓存类型/访问目标对,以便以后的访问只是缓存中的查找,使其比反射更快

Dynamic关键字在内部是反射的包装器

即使这是真的(见上文),这怎么会是一个消极点?无论它是否包装反射,都不应该在任何重大问题上影响您的应用程序

动态类型可能会成为难以发现的bug的滋生地

虽然这是真的,但只要你谨慎使用它,就不会有那么大的问题。此外,如果您基本上将其用作反射的替代品(也就是说,当您希望通过反射访问某些内容时,仅在尽可能短的时间内使用dynamic),那么发生此类错误的风险不应该比使用反射访问您的方法/属性的风险高得多(当然,如果你让每件事都充满活力,那么问题就更大了)

影响与以前.NET版本的互操作性

因此,你必须自己决定这对你来说有多重要

请帮我看看我遇到的赞成和反对意见是否合理

我对您的优缺点感到担忧的是,其中一些并没有解决使用反射和使用动态之间的差异。动态类型会导致在任何动态类型系统的运行时为真之前无法捕获的错误。反射代码与使用动态类型的代码一样可能存在错误

与其从正反两方面来考虑,不如从更中立的角度来考虑。我想问的问题是“使用反射和使用动态类型之间有什么区别?”

首先:通过反射,你可以得到你想要的东西。通过动态,你可以得到C#编译器在编译时得到的类型信息。这可能是两个完全不同的