为什么在C#中允许覆盖静态方法

时间:2010-11-16 17:04:23

标签: c# inheritance static

protected static new void WhyIsThisValidCode()
{
}

为什么允许覆盖静态方法? 除了虫子之外什么也没有,它根本不会像你想象的那样起作用。

参加以下课程。

class BaseLogger
{
    protected static string LogName { get { return null; } }

    public static void Log(string message) { Logger.Log(message, LogName); }
}

class SpecificLogger : BaseLogger
{
    protected static string LogName { get { return "Specific"; } }
}

这是和,代码

SpecificLogger.Log("test");

是另一种情况,但它不会通过查看代码来实现您的想法。

它使用Logger.Log调用LogName = null

那为什么允许这样做?

6 个答案:

答案 0 :(得分:24)

new关键字不会覆盖方法。它改为创建一个与原始方法无关的同名新方法。无法覆盖静态方法,因为它们不是虚拟的

答案 1 :(得分:15)

你没有压倒它,你正在隐藏它。普通方法会表现出完全相同的行为,因此这里没有任何特定的静态方法。

隐藏仅在少数情况下有用。我经常遇到的一个问题是在派生类中使返回类型更具体。但我从来没有使用静态方法。

具有特定名称的静态函数可能有用的一个区域是,如果您使用反射并希望通过从方法返回来获取每个类的信息。但当然,在大多数情况下,属性更适合。

由于您的代码产生了编译器警告,因此不太可能创建错误:

  

警告'StaticHiding.SpecificLogger.LogName'隐藏继承的成员'StaticHiding.BaseLogger.LogName'。如果想要隐藏,请使用new关键字。

如果您使用new,您应该知道自己在做什么。

答案 2 :(得分:10)

答案 3 :(得分:2)

静态方法和字段不属于类实例,而属于类定义。静态方法不参与虚拟调度机制,也不属于虚方法表。

它们只是该特定类的方法和字段。

看起来方法和字段可能是“继承的”,因为你可以做SpecificLogger.Log(),但这只是让你不必一直引用基类的。

静态方法和字段实际上只是全局方法和字段,只是OO类型。

答案 4 :(得分:0)

您没有覆盖基类中的属性,而是隐藏它。运行时使用的实际属性取决于您正在使用的接口。以下示例说明:

SpecificLogger a = new SpecificLogger();
BaseLogger b = new SpecificLogger();

Console.Write(a.Log); // Specific
Console.Write(b.Log); // null

在您的代码中,Log方法实际上是针对BaseLogger接口的 - 因为Log方法是BaseLogger类的一部分。

无法覆盖静态方法和属性,并且当您要隐藏属性时,应使用new关键字来表示您隐藏了某些内容。

答案 5 :(得分:0)

令我惊讶的是,允许使用以下代码并在.net Framework 4.5.1,VS 2013上编译时没有任何错误。

class A
{
    public static void Foo()
    {
    }
}

class B : A
{

}

class Program
{
    static void main(string[] args)
    {
        B.Foo();
    }
}