在阅读了对该主题的许多回复后,我发现许多不喜欢它的人都提到了滥用新关键字的可能性。我的问题是,什么样的虐待?这怎么可能被滥用得如此糟糕,以至于人们非常讨厌它?仅仅是纯粹主义吗?还是有一个我没有看到的真正陷阱?
7 回答
我认为人们对这个特性表达的很多反感归结为“这是一个糟糕的语言特性,因为它会让糟糕的开发人员编写糟糕的代码。” 如果您考虑一下,按照这种逻辑,所有语言功能都很糟糕。
当我遇到一些天才以 为前缀的 VB 代码块时On Error Resume Next
,我诅咒的不是 VB。也许我应该,我想。但根据我的经验,一个决心在保险丝盒里放一分钱的人会找到办法。就算你掏空他的口袋,他也会自己掏腰包。
我,我期待 C# 和 Python 之间有更有用的互操作方式。我正在编写越来越多的代码来做到这一点。对于dynamic
那个特定的用例,关键字不能很快出现,因为目前的做法让我觉得我是 1950 年代前往西方参加会议的苏联学者:有大量的规则和在我离开之前的文书工作,我很确定有人会一直看着我在那里,我在那里捡到的大部分东西都会在我回来时在边境被带走。
有些人认为它是一种会被滥用的工具。就像 VB 中的“Option Strict Off”和“On Error Resume Next”,C# 和 Java 等“纯”语言从未有过。
许多人对“var”关键字也这么说,但我没有看到它被滥用,一旦它被理解为与 VB 的“Variant”不同
在懒惰的开发人员不想对类进行类型检查而只是尝试捕获动态调用而不是写“if blah is Blah ...”的地方可能会滥用它。
我个人觉得它可以在我最近回答的这个问题的情况下正确使用。
我认为真正理解它的力量的是那些对动态 .NET 语言非常感兴趣的人。
动态是不好的,因为这样的代码会到处出现:
public dynamic Foo(dynamic other) {
dynamic clone = other.Clone();
clone.AssignData(this.Data);
return clone ;
}
代替:
public T Foo<T>(T other) where T: ICloneable, IAssignData{
T clone = (T)other.Clone();
clone.AssignData(this.Data);
return clone;
}
第一个,没有静态类型信息,没有编译时检查,它不是自我记录,没有类型推断,所以人们将被迫在调用站点使用动态引用来存储结果,导致更多的类型丢失,以及所有这呈螺旋式下降。
我已经开始害怕动态了。
编辑:危险已经过去(呼!)......毕竟动态并没有被滥用,3年后不需要投票给我:)
真正的陷阱?严重缺乏文档。整个应用程序的架构存在于编写它的人(或多个人)的脑海中。至少使用强类型,您可以通过其类定义查看对象的作用。使用动态类型,您充其量只能从它的使用中推断出含义。在最坏的情况下,您不知道对象是什么。这就像用 JavaScript 编写所有东西一样。确认!
当人们意识到他们无法通过 获得良好的 IntelliSense 时dynamic
,他们会从“dynamic
快乐”转变为“dynamic
在必要时”和var
“在所有其他时间”。
目的dynamic
包括:与 COM/C++ 和 DLR/IronPython/IronRuby 等动态语言和平台的互操作性;以及将 C# 本身变成 IronSmalltalkWithBraces 并实现IDynamicObject
.
所有人都会有美好的时光。(除非您需要维护其他人编写的代码。)
这有点像讨论公共摄像机,当然它们可以并且将会被滥用,但拥有它们也有好处。
如果你不需要它们,你没有理由不能在你自己的编码指南中取缔“动态”关键字。所以有什么问题?我的意思是,如果你想用“动态”关键字做一些疯狂的事情,并假装 C# 是 JavaScript 的一些突变表亲,请做我的客人。只需将这些实验排除在我的代码库之外。;)
我看不出当前动态调用方法的方式存在缺陷的原因:
它需要三行来完成,或者您可以在 System.Object 上添加一个扩展方法来为您完成:
class Program
{
static void Main(string[] args)
{
var foo = new Foo();
Console.WriteLine(foo.Invoke("Hello","Jonathan"));
}
}
static class DynamicDispatchHelper
{
static public object Invoke(this object ot, string methodName, params object[] args)
{
var t = ot.GetType();
var m = t.GetMethod(methodName);
return m.Invoke(ot, args);
}
}
class Foo
{
public string Hello(string name)
{
return ("Hello World, " + name);
}
}