2012-01-11 81 views
3

已经遇到扩展的更先进的碰撞问题和静态方法我举例说明,并简化一些代码:扩展方法和静态方法不匹配在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”)。

我发布这个没有详细介绍为什么编译器会提醒程序员(已经知道规则),但更多的是为了提高讨论的内容,这将是对这种问题的近乎或最终的解决方案在微软之前,人们可以很容易地告诉扩展/静态方法调用匹配,而编译器甚至不提供确切的程序员的错误描述或提示。

期待从'stackoverflowers'听到。

+0

你说'a.To()'失败了,但是你引用的错误信息是A.To()'。你是什​​么意思? – Justin 2012-01-11 18:29:25

+0

@Justin,不,他说得对。 – Shymep 2012-01-11 18:30:35

+0

@Shymep - 你说得对 - 请不理我以前的评论。 – Justin 2012-01-11 18:32:08

回答

10

首先,你的“问题”显然是一个讨论的呼吁。因此,它将被关闭,因为讨论的呼吁不是问题。 StackOverflow不是一个讨论网站;有任何数量的论坛可以用来进行讨论。这是提问的好地方。

澄清情况:这里发生了什么是:

  • 重载决策确定呼叫a.To()在静态方法的形式适用候选人
  • 该方法是静态的,但接收者是一个实例的事实不会使候选不适用。相反,它使得超负荷分辨率出现错误,将其选为最佳适用候选人。
  • 扩展方法根本不检查,除非没有适用的候选。有一个适用的候选人,虽然是非法的,所以扩展方法不检查。

我同意这有点奇怪,但分析是正确和可取的。语言设计者必须决定什么更可能:呼叫者打算调用静态方法,但错误地键入“A”作为“A”,或者调用者打算调用一些完全不同的方法,这可能会扩展某些类型的兼容性与“一个”。更安全的假设是前者,因此我们给出错误。

我知道有些人可能会觉得这个分析有点奇怪。这有点奇怪,但它确实有道理。如果你认为这些规则是神秘而混乱的,那你是对的。这是在十多年的时间内将新规则用于现有算法时发生的情况。

C#中的重载解析最初设计用于处理非常简单的语言; “params”是重载决议中最复杂的部分。它现在必须处理泛型,类型推断,扩展方法,动态以及命名和可选参数。所有这些变化都严重强调了重载解析算法,因为每次添加新特征时,我们都必须确保旧特征继续保持一致。

关于您的具体情况:如果它伤害,当你这样做然后不要那样做。制作具有相同名称的静态,实例和扩展方法是一个非常糟糕的主意。他们不太可能做同样的事,所以不要让他们有同名

编译器甚至不提供确切的程序员的错误描述或提示。

废话。编译器告诉你到底什么是错误的:重载解析选择了一个静态方法,并且你用一个实例作为接收者调用它。这是程序中的错误,这是报告的错误。