以下方法或属性(一个静态和一个非静态)之间的调用不明确

时间:2015-04-14 22:48:57

标签: c#

为什么我不允许使用具有相同签名的静态和非静态方法?

我们说我有这样的课程

public class TestClass
{
    public object thing { get; set; }

    public TestClass()
    {

    }

    public TestClass(object thing)
    {
        this.thing = thing;
    }

    public static TestClass ConvertTestClass(object thing)
    {
        return new TestClass(thing);
    }

    public TestClass ConvertTestClass(object thing)
    {
        this.thing = thing;
        return this;
    }


}

我试着像这样使用它

public class SomeOtherClass
{
    public SomeOtherClass()
    {
        TestClass tc = TestClass.ConvertTestClass(new object());

        TestClass tc2 = new TestClass();
        tc2.ConvertTestClass(new object());
    }
}

我在TestClass.ConvertTestClass(new object());

上收到以下错误
  

以下方法或属性之间的调用不明确:' TestClass.ConvertTestClass(object)'和' TestClass.ConvertTestClass(对象)'

以及tc2.ConvertTestClass(new object());

上的这些错误
  

以下方法或属性之间的调用不明确:' TestClass.ConvertTestClass(object)'和' TestClass.ConvertTestClass(对象)'

     

会员' TestClass.ConvertTestClass(对象)'无法使用实例引用访问;使用类型名称来限定它

编译器真的不能区分该方法的静态和非静态版本,或者我在这里遗漏了什么?

我没有使用ReSharper(在其他问题中似乎是类似问题的根源)。

2 个答案:

答案 0 :(得分:4)

它给你一个错误,因此可以安全地认为编译器不能或不会在两种方法之间辨别。

无论如何都要做这种过载可能是一个坏主意,因为它不清楚你打算调用哪种方法,但如果这还不够,C#5规范定义了一个方法签名,如这(第3.6节):

  

方法的签名由方法的名称组成   类型参数的数量以及类型和种类(值,参考或   输出)每个形式参数,按左侧顺序考虑   对。出于这些目的,该方法的任何类型参数   在形式参数的类型中发生的不是由它识别的   name,但是通过它在类型参数列表中的序号位置   方法。方法的签名特别不包括   返回类型,可以为其指定的params修饰符   最右边的参数,也没有可选的类型参数约束。

它没有明确提及static,但它也没有将其作为"签名"的定义的一部分。因此,可以假设,通过规范,方法重载只能在静态或实例化的事实上有所不同。

答案 1 :(得分:0)

我将此作为评论写下来,但在适当的编辑器中更容易理解这一点。

我认为你只是考虑从外部调用类的方法的逻辑,即从另一个类调用。在具有相同签名的类方法中,只有静态不同才有意义。例如,你有一个有两种方法的类,如下所示

public class MyClass
{
    public static void HellowWorld()
    {
        Console.WriteLine("Hello World!");
    }

    public void HellowWorld()
    {
        Console.WriteLine("Howdy World!");
    }

    public void Greet()
    {
        HellowWorld();
    }
} 

在编译时,只要其中一个方法被注释掉,它就会看到它编译没有错误。您应该能够替换注释掉的方法并成功编译该类。表明在类的范围内无法区分应该调用哪种方法。

你可能会争辩说,在课堂上,你应该被迫使用相同的语法来调用静态方法,例如。

MyClass.HelloWorld();

但是,这会违反整个C#中使用的作用域逻辑,为什么需要在类中指定类名?我认为这样的改变也会造成模棱两可的现象,而现在这样做当然会破坏很多代码。

我认为编译器逻辑非常有意义。