2014-01-31 91 views
1

在我的许多尝试中找到一个很好的解决方案在C#中的静态覆盖(在Objective-C中很容易,所以不要告诉我“这是不可能的”,或者说“只有对象是多态的“,因为我知道)我试着用代表的方法。我的代码是:静态代理和覆盖

public class Animal 
{ 
    public static Func<string> Name { get; protected set; } 

    static Animal() 
    { 
     Name =() => "Animal"; 
    } 
} 

public class Cat : Animal 
{ 
    static Cat() 
    { 
     Name =() => "Cat"; 
    } 
} 

但是当我打电话Cat.Name()我仍然得到“动物”。我不是在寻求解决方案,我问:为什么?

+1

1)字段'Animal.Name'只有一个实例。没有单独的“Cat.Name”。 'Cat.Name'和'Animal.Name'将总是返回相同的值,Cat或者Animal取决于哪个静态构造函数是最近运行的。 2)静态构造函数还没有运行,所以它仍然返回旧名称。静态构造函数只有在访问Cat的成员(或构造它的一个实例)时才会运行,即使通过Cat来访问,也不会生成Animal.Name。 – CodesInChaos

+1

我会用反射和泛型的混合来解决你最初的问题。泛型类将为每种类型都有一个独特的静态字段。 – CodesInChaos

+0

这是一个好主意,你建议用类似“动物”,“动物”,......来代替一个课程方案吗? – Gerard

回答

1
  1. 该字段只有一个实例Animal.Name。没有单独的Cat.Name

    这意味着Cat.NameAnimal.Name总是返回相同的值,无论是CatAnimal取决于哪个静态构造函数是最近期的运行。

  2. 静态构造函数尚未运行,所以它仍然返回旧名称。静态构造函数只在访问Cat的静态成员(或构造它的一个实例)时运行。 Cat.Name从这个意义上说不是Cat的成员,因为它实际上是Animal.Name

    规格说,关于何时执行静态构造函数:

    对于封闭类类型的静态构造函数在给定的应用程序域中执行最多一次。静态构造的执行由第一以下事件触发的应用程序域内发生:
    ·创建类型的一个实例。
    ·引用了类类型的任何静态成员。

1

没有在.NET静态方法的继承。就IL而言,Cat.Name不存在,但.NET允许您从子类调用基类的方法。这解释了为什么永远不会调用静态Cat构造函数。

作为NameAnimal猫不的方法,Animal.Name被触发,因此,Animal's构造将会运行。结果是:你是一只动物,而不是一只猫。

.NET Static Constructors on MSDN