扩展方法和静态方法不匹配在C#中的原型匹配
已经遇到扩展的更先进的碰撞问题和静态方法我举例说明,并简化一些代码:扩展方法和静态方法不匹配在C#中的原型匹配
using System;
namespace Test
{
static class EM
{
public static string To(this object o)
{
return o.GetType().ToString();
}
}
class A
{
public static string To() { return "Test.A"; }
}
class B { }
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
object o = null;
o.To();
B b = null;
b.To();
A a = null;
a.To();
A.To();
}
}
}
我给自己买了惊讶,当.NET编译器,范围从3.x到4.y未能解决应在“a.To();
”出现的行中调用哪种方法。当然,我解释了编译器,但这就是错误信息可以带到的地方(字面意思是“Member 'Test.A.To()' cannot be accessed with an instance reference; qualify it with a type name instead
”)。
我发布这个没有详细介绍为什么编译器会提醒程序员(已经知道规则),但更多的是为了提高讨论的内容,这将是对这种问题的近乎或最终的解决方案在微软之前,人们可以很容易地告诉扩展/静态方法调用匹配,而编译器甚至不提供确切的程序员的错误描述或提示。
期待从'*ers'听到。
首先,你的“问题”显然是一个讨论的呼吁。因此,它将被关闭,因为讨论的呼吁不是问题。 *不是一个讨论网站;有任何数量的论坛可以用来进行讨论。这是提问的好地方。
澄清情况:这里发生了什么是:
- 重载决策确定呼叫
a.To()
在静态方法的形式适用候选人。 - 该方法是静态的,但接收者是一个实例的事实不会使候选不适用。相反,它使得超负荷分辨率出现错误,将其选为最佳适用候选人。
- 扩展方法根本不检查,除非没有适用的候选。有是一个适用的候选人,虽然是非法的,所以扩展方法不检查。
我同意这有点奇怪,但分析是正确和可取的。语言设计者必须决定什么更可能:呼叫者打算调用静态方法,但错误地键入“A”作为“A”,或者调用者打算调用一些完全不同的方法,这可能会扩展某些类型的兼容性与“一个”。更安全的假设是前者,因此我们给出错误。
我知道有些人可能会觉得这个分析有点奇怪。这有点奇怪,但它确实有道理。如果你认为这些规则是神秘而混乱的,那你是对的。这是在十多年的时间内将新规则用于现有算法时发生的情况。
C#中的重载解析最初设计用于处理非常简单的语言; “params”是重载决议中最复杂的部分。它现在必须处理泛型,类型推断,扩展方法,动态以及命名和可选参数。所有这些变化都严重强调了重载解析算法,因为每次添加新特征时,我们都必须确保旧特征继续保持一致。
关于您的具体情况:如果它伤害,当你这样做然后不要那样做。制作具有相同名称的静态,实例和扩展方法是一个非常糟糕的主意。他们不太可能做同样的事,所以不要让他们有同名。
编译器甚至不提供确切的程序员的错误描述或提示。
废话。编译器告诉你到底什么是错误的:重载解析选择了一个静态方法,并且你用一个实例作为接收者调用它。这是程序中的错误,这是报告的错误。
你说'a.To()'失败了,但是你引用的错误信息是A.To()'。你是什么意思? – Justin 2012-01-11 18:29:25
@Justin,不,他说得对。 – Shymep 2012-01-11 18:30:35
@Shymep - 你说得对 - 请不理我以前的评论。 – Justin 2012-01-11 18:32:08