2014-01-31 5 views
1

В одном из моих многочисленных аттестатов, чтобы найти хорошее решение для статического переопределения на C# (это легко в объективе 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() я все еще получаю "Animal". Я не прошу разрешения, я спрашиваю: почему?

+1

1) Существует только один экземпляр поля 'Animal.Name'. Не существует отдельного «Cat.Name». «Cat.Name» и «Animal.Name» всегда будут возвращать одно и то же значение: «Cat» или «Animal» в зависимости от того, какой статический конструктор был последним для запуска. 2) Статический конструктор еще не запущен, поэтому он все еще возвращает старое имя. Статический конструктор запускается только при доступе к члену 'Cat' (или конструировать его экземпляр), который« Animal.Name »не существует, даже если он доступен через« Cat ». – CodesInChaos

+1

Я бы решил вашу оригинальную проблему с сочетанием отражений и дженериков. У классов обобщений будет определенное статическое поле для каждого типа. – CodesInChaos

+0

Это отличная идея, вы предлагаете заменить схему классов чем-то вроде «Animal », «Animal ', ...? – Gerard

ответ

1
  1. Есть только один экземпляр поля Animal.Name. Нет отдельного Cat.Name.

    Это означает, что Cat.Name и Animal.Name всегда возвращают то же значение, либо Cat или Animal в зависимости от статического конструктора был последним для запуска.

  2. Статический конструктор еще не запущен, поэтому он все еще возвращает старое имя. Статический конструктор запускается только при обращении к статическому элементу Cat (или созданию экземпляра его). Cat.Name не является членом Cat в этом смысле, так как это фактически Animal.Name.

    Спецификации говорит о том, когда запускать статические конструкторы:

    Статический конструктор закрытого типа класса максимум один раз выполняет в данной предметной области. Выполнение статического конструктора запускается первым из следующих событий, которые происходят в домене приложения:
    · Создан экземпляр типа класса.
    · Указаны любые статические элементы типа класса.

1

Там нет наследования статических методов в .NET. В терминах IL, Cat.Name не существует, однако .NET позволяет вызывать метод базового класса из подкласса. Это объясняет, почему статический конструктор Cat никогда не вызывается.

В Name представляет собой метод Animal и не Кота, Animal.Name срабатывает и, следовательно, Animal's конструктор будет работать. Результат: вы животное, а не кошка.

.NET Static Constructors on MSDN

Смежные вопросы