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
。
那为什么允许这样做?
答案 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();
}
}