为什么我的静态方法隐藏了我的实例方法?

时间:2009-04-16 16:22:12

标签: c# .net

以下代码是否应发出警告?

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { public static void Do()  { /*...*/ } /*...*/ }

它给出了:

  

“警告CS0108:'Bar.Do()'隐藏继承的成员'Foo.Do()'。如果想要隐藏,请使用new关键字。”

如果我对代码进行了更改:

class Foo { public static void Do() { /*...*/ } /*...*/ }
class Bar : Foo { public void Do()  { /*...*/ } /*...*/ }

我得到同样的警告。

但是,如果我做出以下更改,警告就会消失。

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { new public static void Do() { /*...*/ } /*...*/ }

让我做出进一步的改变:

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { 
    new public static void Do() 
    { new Bar().Do();/*...*/ } /*...*/ 
}

这不编译:

  

“错误CS0176:无法使用实例引用访问成员'Bar.Do()';而是使用类型名称限定它。”

因此,我无法通过静态方法的实例引用访问我继承的方法!

它背后的逻辑是什么?或者我在某个地方打错了?

当我尝试为从'Form'派生的表单定义一个静态方法'Show'时,我遇到了这个。

6 个答案:

答案 0 :(得分:5)

您认为该错误在哪里?有警告的事实是绝对正确的。从C#3.0规范,第10.3.4节:

  

类成员声明是   允许宣布成员   同名或签名作为继承   会员。当这种情况发生时,派生出来   据说集体成员隐藏基地   班级成员。隐藏遗传   成员不被视为错误,但是   它确实会导致编译器发出一个   警告。要压制警告,   派生类的声明   成员可以包含一个新的修饰符   表明派生成员是   旨在隐藏基础成员。

您的方法调用失败的事实是更微妙的,但它基本上是因为成员查找算法选择静态方法,然后使用7.5.5.1节的这一部分:

  

最佳选择的最终验证   方法执行:

     

方法是   在方法的上下文中验证   group:如果最好的方法是静态的   方法,方法组必须具备   由一个简单的名字或一个   成员访问类型。如果   最好的方法是实例方法,   方法组必须由a产生   简单名称,成员访问通过   变量或值,或基本访问。   如果这些要求都不是   如果是,则发生编译时错误。

答案 1 :(得分:2)

不,这很有道理。这按预期工作:

using System;
using System.Collections.Generic;

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { 
    new public static void Do() 
    { ((Foo)new Bar()).Do();/*...*/ } /*...*/ 
}

那是因为编译器假定您有一个Bar类型,然后找到静态成员。通过将它转换为Foo(它是免费的btw。),你可以在foo()的元数据中查找它,一切都很好。

答案 2 :(得分:2)

试试这个:

        new public static void Do()
        { 
            ((Foo)new Bar()).Do(); 
        }

答案 3 :(得分:1)

你应该可以通过调用base.Do()而不是Bar()调用它.Do()

答案 4 :(得分:0)

在最终的代码示例中,Bar.Do()声明中的new关键字表示您打算隐藏Foo.Do()。

答案 5 :(得分:0)

出于好奇,你为什么要这样做?看起来你可能错误地解决了你的解决方案。

上面的代码似乎正常工作,编译器消息告诉你问题是什么。