2010-09-23 214 views
5

我不明白以下现象,有人可以解释我,请问我错了什么?继承和静态属性

public class BaseClass 
{ 
    public BaseClass() 
    { 
     BaseClass.Instance = this; 
    } 

    public static BaseClass Instance 
    { 
     get; 
     private set; 
    } 
} 

public class SubClassA : BaseClass 
{ 
    public SubClassA() 
     : base() 
    { } 
} 

public class SubClassB : BaseClass 
{ 
    public SubClassB() 
     : base() 
    { } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     SubClassA a = new SubClassA(); 
     SubClassB b = new SubClassB(); 

     Console.WriteLine(SubClassA.Instance.GetType()); 
     Console.WriteLine(SubClassB.Instance.GetType()); 

     Console.Read(); 
    } 
} 

我的理解,编译器应生成通过继承一个新的类型,SubClassA和SubClassB真的是自己的类型与自己的静态变量。但是,似乎该类的静态部分不是被继承的,而是被引用的 - 我得到什么错误?

回答

10

.NET中的继承只适用于实例库。静态方法在类型级别上定义,而不是在实例级别上定义。这就是为什么覆盖不适用于静态方法/属性/事件...

静态方法只在内存中保留一次。没有为他们创建的虚拟表等。

如果您在.NET中调用实例方法,则始终将其指定为当前实例。这是由.NET运行时隐藏的,但它发生了。每个实例方法都有一个指向运行该方法的对象的指针(引用)作为第一个参数。这不会发生在静态方法上(因为它们是在类型层次上定义的)。编译器应该如何决定选择要调用的方法?

+0

我不明白为什么继承只适用于情况,但我必须接受它。谢谢你提供的信息。 – 2010-09-23 08:17:55

+0

在PHP和Delphi中实现相同的行为 – 2010-11-22 09:11:02

+0

@VladislavRastrusny:我不知道它是如何在2010年。但现在在2016年,在PHP中有'self ::'和'static ::'。 – 2016-10-22 08:30:09

13

只有一个静态Instance属性,它在BaseClass中定义,它也是碰巧是唯一可以更改它的类型(因为该集合是private)。

发生什么事是你的子类SubClassASubClassB每个调用构造函数在他们自己的构造函数。此构造函数将Instance设置为正在初始化的BaseClass实例。

您示例代码中的最后一个这样的实例恰好是SubClassB的一个实例;因此一个Instance属性设置为此实例到达您的Console.WriteLine调用。

您可以取消您的SubClassASubClassB对象的构建,您将看到Instance设置为SubClassA的实例。

+0

+1也用于解释为什么它将SubClassB写入两次 – 2010-09-23 07:54:35