Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果父类和子类有一个同名的静态方法,为什么会将其视为方法隐藏?_C#_.net_Inheritance_Static - Fatal编程技术网

C# 如果父类和子类有一个同名的静态方法,为什么会将其视为方法隐藏?

C# 如果父类和子类有一个同名的静态方法,为什么会将其视为方法隐藏?,c#,.net,inheritance,static,C#,.net,Inheritance,Static,如果声明继承层次结构,其中父类和子类都具有相同名称和参数*的静态方法,Visual Studio将发出警告: 例如: public class BaseClass { public static void DoSomething() { } } public class SubClass : BaseClass { public static void DoSomething() { } } :警告CS0108:'SubClass.DoSome

如果声明继承层次结构,其中父类和子类都具有相同名称和参数*的静态方法,Visual Studio将发出警告:

例如:

public class BaseClass
{
    public static void DoSomething()
    {
    }
}

public class SubClass : BaseClass
{
    public static void DoSomething()
    {
    }
}
:警告CS0108:'SubClass.DoSomething()'隐藏继承的成员'BaseClass.DoSomething()'。如果要隐藏,请使用新关键字。

为什么这种方法被认为是隐藏的?这两个方法都不涉及继承层次结构,只能使用类名调用:

BaseClass.DoSomething();
SubClass.DoSomething();
public Class A
{
     public static void C() {...}
}

public Class B: A
{

}

B.C() // Valid call!
或者,在课堂上不合格。在任何一种情况下,调用哪个方法都没有歧义(即,没有“隐藏”)

*有趣的是,这些方法可以根据返回类型不同而产生相同的警告。但是,如果方法参数类型不同,则不会生成警告


请注意,我并不是试图为静态继承或任何其他类似的废话创建一个论点或讨论它

子类的成员将无法从基类访问DoSomething,除非明确指示类名。因此,它实际上对子类的成员是“隐藏”的,但仍然是可访问的

例如:

public class SubClass : BaseClass
{
    public static void DoSomething()
    {
    }

    public static void DoSomethingElse()
    {
        DoSomething(); // Calls SubClass
        BaseClass.DoSomething(); // Calls BaseClass
    }
}

这只是一个警告。编译器只是想确保您有意使用相同的方法名

为什么这种方法被认为是隐藏的?这两个方法都不涉及继承层次结构,只能通过使用类名来调用

事实并非如此。您可以从任何继承的类名调用DoSomething:

BaseClass.DoSomething();
SubClass.DoSomething();
public Class A
{
     public static void C() {...}
}

public Class B: A
{

}

B.C() // Valid call!
这就是为什么如果在B中声明具有相同签名的方法,就要隐藏C()


希望这有帮助。

Visual Studio和Philippe说这是一个警告,因此您的代码将编译并运行

然而,“Code裸体”很好地说明了为什么它是隐藏的。此代码编译时不会抛出错误或警告。多亏了“代码裸体”

public class BaseClass {
    public virtual void DoSomething() {
    }
}

public class SubClass : BaseClass {
    public override void DoSomething() {

    }

    public void DoSomethingElse() {
        DoSomething(); // Calls SubClass
        base.DoSomething(); // Calls BaseClass
    }
}
编辑: 使用Travis的代码,我可以执行以下操作:
基类DoSomething()
子类DoSomething()


而且效果很好。问题是,您可能想知道为什么子类继承自基类,而两者都实现相同的静态方法。事实并非如此,这两个类都实现了可能完全不同但名称相同的方法。这可能令人困惑

有一件事是肯定的——方法在c#中不会因返回类型而有所不同。这不是静态的情况,每种类型的方法都是如此。它们也不与它们的访问修饰符相区别。如果我不是故意使用相同的方法名,那有什么问题?我不明白你的意思。通过明确地指定“新”,你告诉编译器你打算使用相同的方法签名。我认为两者之间的解释最好,包括你的基本假设是错误的。考虑非静态方法。如果我有两个同名的方法,并且我正在进行调用,则可能存在歧义。在静态的情况下,这种模糊性并不容易存在(尽管关于它可能存在的地方,请参见@Code裸体的回复中的类似示例),这是一个很好的例子,尽管不像非静态虚拟方法的原理那样令人信服。如果
DoSomethingElse()
是在子类中声明的,可能会是一个更好的例子。@Travis-好的观点。继承链越往下走,就越容易混淆:-)我认为混淆与静态类有关,所以到处删除关键字并不能真正帮助回答这个问题。如果你让你的方法都是静态的,我想你会得到一些警告,甚至可能是错误。这是一个很好的例子——这就是为什么我问关于静态方法的问题。使用虚拟/非虚拟方法的实例方法案例完全有意义。静态是一个让人毛骨悚然的地方。使用上面的代码,如果添加Static关键字,就会出现错误,代码也不会编译。静态类和方法的问题是,不必先实例化类。我考虑过这一点,但这似乎很愚蠢。调用B.C()确实有效,但其意图值得怀疑。如果随后在B中引入方法C,则重新编译会将其更改为调用新引入的方法。注意,如果您不重新编译B.C()调用(如果它在不同的程序集中,等等),它仍然会引用a.C()。我不确定我是否理解您的意思。这正是编译器在实现B.C()时警告您的原因:在不知不觉中通过B call B.C()调用时,您可能会错误地使任何调用程序都希望使用A.C()。如果您添加“new”关键字,则显式地让编译器知道您要隐藏A的C()实现,并使B中的任何调用方解析为B.C()(请注意,A.C()仍将在A中执行原始实现)。也许更好的问题是“B.C()为什么要编译?”开始。=)对于实例方法,您的参数是有意义的,因为它们是继承的。静态方法不是,但通过允许像B.C()这样的东西进行编译(当B不声明C方法时)会产生这种错觉。我认为@Code裸体的答案反映了一个更实际的例子。为什么B.C()编译是一个很好的观点,但这不是当前的问题。事实上,它确实可以编译,因此警告是有意义的。否则,您将隐藏在中定义的方法,而没有任何反馈。警告显然是更好的选择。