gre*_*man 5 c# generics templates d
我正在阅读Andrei Alexandrescu撰写的"D编程语言",一句话让我感到困惑.考虑这样的代码(第138页):
T[] find(T)(T[] haystack, T needle) {
while (haystack.length > 0 && haystack[0] != needle) {
haystack = haystack[1 .. $];
}
return haystack;
}
Run Code Online (Sandbox Code Playgroud)
并致电(第140页):
double[] a = [ 1.0, 2.5, 2.0, 3.4 ];
a = find(a, 2); // Error! ' find(double[], int)' undefined
Run Code Online (Sandbox Code Playgroud)
解释(代码下面的段落):
如果我们眯着眼睛够硬,我们也看到,在这种情况下,主叫方的意图是具有
T = double和从漂亮的隐式转换受益int于double.然而,在一般情况下,让语言同时组合地尝试隐式转换和类型推导是一个冒险的命题,因此D不会尝试做所有这些.
我感到困惑,因为像C#这样的语言试图推断出类型 - 如果它不能这样做,用户会得到错误,但是如果可以,那么它就可以了.C#和它一起生活了几年,我没有听到任何关于这个功能如何破坏某个人日子的故事.
所以我的问题是这个 - 在上面的例子中推断类型涉及哪些危险?
我只能看到优点,很容易编写泛型函数,很容易调用它.否则,您必须在泛型类/函数中引入更多参数,并且仅为了推断类型而编写表示允许转换的特殊约束.
首先要注意的是,它并不是说类型推导有问题,而是说类型推导和隐式转换同时存在问题。
所以,如果你有:
a = find(a, 2.0);
Run Code Online (Sandbox Code Playgroud)
然后它很乐意推断double为类型。
如果显式键入 double,则很高兴推断出2应该隐式转换为2.0.
它不会同时做这两件事。
现在,C# 确实做到了这一点。我认为在很大程度上我同意你的观点,它通常很方便并且通常运行良好。
同时,它确实可能会令人困惑,特别是在它导致多个同样合理的过载的情况下。
为什么类型推断和隐式运算符在以下情况下不起作用?为什么带有隐式转换运算符的自定义结构上的 Assert.AreEqual 失败?这两个问题都是关于为什么隐式转换和类型推断的特定组合不起作用。
隐式转换对委托类型推断的意外影响还有其他因素,但同样,由于参数类型不匹配而拒绝考虑可能匹配列表中的方法就意味着问题没有发生。
如果答案始终是“因为您同时进行隐式转换和类型推断,而这是不支持的”,那么它们都会简单得多。这就是 D 的答案。
但另一方面,此类问题并不经常出现,因此我仍然赞成 C# 设计决策允许两者同时存在,但存在一些问题意味着不允许它们仍然是一个合理的设计决策。