Странности наследования от абстрактного класса !!!
От: Cynic Россия  
Дата: 23.07.08 00:35
Оценка:
Ещё раз... Написал абстрактный класс А с единственным членом — списком. Наследуясь от него создаю класс В, где статический конструктор добавляет в этот список один элемент. Потом в программе беру класс B, а список пуст Переношу объявление списка в класс B, все работает. Почему
abstract class A
{
    public static List<string> strList = new List<string>();;
}

class B : A
{
    //public static  List<string> strList = new List<string>(); //Если это откомментировать всё заработает!

    static B()
    {
        strList.Add("string");
    }
}

class Test
{
    public static void Main()
    {
        Console.WriteLine(B.strList);
    }
}
:)
Re: Странности наследования от абстрактного класса !!!
От: TK Лес кывт.рф
Дата: 23.07.08 02:52
Оценка: 1 (1)
Здравствуйте, Cynic, Вы писали:

C>Ещё раз... Написал абстрактный класс А с единственным членом — списком. Наследуясь от него создаю класс В, где статический конструктор добавляет в этот список один элемент. Потом в программе беру класс B, а список пуст Переношу объявление списка в класс B, все работает. Почему


В реальности используется A.strList поэтому, инициализации и не происходит.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Странности наследования от абстрактного класса !!!
От: nikov США http://www.linkedin.com/in/nikov
Дата: 23.07.08 08:45
Оценка: 3 (2)
Здравствуйте, Cynic, Вы писали:

C>Написал абстрактный класс А с единственным членом — списком. Наследуясь от него создаю класс В, где статический конструктор добавляет в этот список один элемент. Потом в программе беру класс B, а список пуст Переношу объявление списка в класс B, все работает. Почему


Дело тут совсем не в том, что класс A — абстрактный. Похоже, это дефект в спецификации C#. Она говорит:

10.3.3 Inheritance
....
Inheritance means that a class implicitly contains all members of its direct base class type, except for the instance constructors, destructors and static constructors of the base class.


Таким образом, статические поля базового класса наследуются и являются членами производного класса. С другой стороны:

10.12 Static constructors
....
The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
• An instance of the class type is created.
• Any of the static members of the class type are referenced.


То есть, если строго придерживаться этих формулировок, обращение к унаследованному статическому полю через производный класс должно вызывать выполнение статического конструктора этого производного класса. Реализовать такое поведеение было бы затруднительно из-за того, что при компиляции стирается разница между обращением к статическому полую через базовый и производный классы. Таким образом самым правильным было бы изменить последнюю строчку в приведенной цитате из 10.12 таким образом:

• Any of the static members declared in the class type are referenced.



Кстати, в спецификации есть еще пару ляпов, связанных с путаницей между членами типа и членами, определенными в типе.
Re: Странности наследования от абстрактного класса !!!
От: BokiyIS  
Дата: 23.07.08 09:16
Оценка:
Здравствуйте, Cynic, Вы писали:

http://www.rsdn.ru/forum/message/179051.1.aspx
Автор:
Дата: 22.01.03
— вот ещё похожий случай.
http://rsdn.ru/forum/message/1195767.1.aspx
Автор: Chupa_Kabra
Дата: 30.05.05
— а вот ещё объяснение (хотя nikov уже и объяснил )
Re[2]: Странности наследования от абстрактного класса !!!
От: matumba  
Дата: 23.07.08 12:02
Оценка:
Здравствуйте, nikov, Вы писали:

N>Реализовать такое поведеение было бы затруднительно из-за того, что при компиляции стирается разница между обращением к статическому полую через базовый и производный классы.


Разница стирается в бинарном коде. Но компилятор-то знает, что было обращение к B.strList! Значит он должен перед этим вставить вызов B.B()
Или я что-то не догоняю?
Re[3]: Странности наследования от абстрактного класса !!!
От: Mab Россия http://shade.msu.ru/~mab
Дата: 23.07.08 12:09
Оценка:
Здравствуйте, matumba, Вы писали:

M>Или я что-то не догоняю?

Эти вызовы -- забота VM, а не компилятора.
Re[2]: Странности наследования от абстрактного класса !!!
От: Cynic Россия  
Дата: 23.07.08 19:34
Оценка:
Здравствуйте, nikov, Вы писали:

Таким образом самым правильным было бы изменить последнюю строчку в приведенной цитате из 10.12 таким образом:

N>

N>• Any of the static members declared in the class type are referenced.


Т.е. в результате приходим к выводу, что статический конструктор класса вызывается только если в нем объявлен ссылочный член или создаётся экземпляр класса. Поэтому в данном случае вызывается только статический конструктор класса A, а не B. Я правильно понял
:)
Re[3]: Странности наследования от абстрактного класса !!!
От: nikov США http://www.linkedin.com/in/nikov
Дата: 23.07.08 19:54
Оценка:
Здравствуйте, Cynic, Вы писали:

C>Т.е. в результате приходим к выводу, что статический конструктор класса вызывается только если в нем объявлен ссылочный член или создаётся экземпляр класса. Поэтому в данном случае вызывается только статический конструктор класса A, а не B. Я правильно понял


Я не понимаю, что такое ссылочный член.
Поправка такая: надо заменить слова "обращение к статическому члену класса" на "обращение к статическому члену, определенному в этом классе".
Re[4]: Странности наследования от абстрактного класса !!!
От: Cynic Россия  
Дата: 23.07.08 20:07
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, Cynic, Вы писали:


C>>Т.е. в результате приходим к выводу, что статический конструктор класса вызывается только если в нем объявлен ссылочный член или создаётся экземпляр класса. Поэтому в данном случае вызывается только статический конструктор класса A, а не B. Я правильно понял


N>Я не понимаю, что такое ссылочный член.

Я имел ввиду, член ссылочного типа.
:)
Re[5]: Странности наследования от абстрактного класса !!!
От: BokiyIS  
Дата: 23.07.08 20:22
Оценка:
Здравствуйте, Cynic, Вы писали:

C>Я имел ввиду, член ссылочного типа.


Вам же nikov писал:

• An instance of the class type is created.
• Any of the static members of the class type are referenced.


А в вашем случае статический конструктор B не запускается, потому что статическая переменная объявлена в классе A. И, как заметил TK, когда вы пишите B.strList, в IL пишется A.strList (посмотрите рефлектором) => запускается статический конструктор класса A, а не B.
Re[6]: Странности наследования от абстрактного класса !!!
От: Cynic Россия  
Дата: 23.07.08 20:34
Оценка:
Здравствуйте, BokiyIS, Вы писали:

BIS>Здравствуйте, Cynic, Вы писали:


C>>Я имел ввиду, член ссылочного типа.


BIS>Вам же nikov писал:


BIS>

BIS>• An instance of the class type is created.
BIS>• Any of the static members of the class type are referenced.


BIS>А в вашем случае статический конструктор B не запускается, потому что статическая переменная объявлена в классе A. И, как заметил TK, когда вы пишите B.strList, в IL пишется A.strList (посмотрите рефлектором) => запускается статический конструктор класса A, а не B.


Чего вы нервничаете? Всё уже посмотрено. Просто хотел уточнить, чтобы в список вопросов записать правильно. Спасибо
:)
Re[7]: Странности наследования от абстрактного класса !!!
От: BokiyIS  
Дата: 23.07.08 20:40
Оценка:
Здравствуйте, Cynic, Вы писали:

C>Чего вы нервничаете? Всё уже посмотрено. Просто хотел уточнить, чтобы в список вопросов записать правильно. Спасибо


Да нет, я не нервничаю, просто меня самого смущало такое поведение Я уже приводил ссылку, если не смотрели — посмотрите
Автор: Chupa_Kabra
Дата: 30.05.05
Re: переоптимизировались?
От: merk Россия  
Дата: 24.07.08 00:21
Оценка:
Здравствуйте, Cynic, Вы писали:

C>Ещё раз... Написал абстрактный класс А с единственным членом — списком. Наследуясь от него создаю класс В, где статический конструктор добавляет в этот список один элемент. Потом в программе беру класс B, а список пуст Переношу объявление списка в класс B, все работает. Почему


а попробуйте добавить в класс B переменную, чтобы он был непустой.
такое впечатление, что это переоптимизация. они видят, что у класса B нет собственных полей, и потому запуск конструктора считают излишним. а у А вообще нет конструктора, насколько я понимаю этот шарп.
если версия верна, то проблема в отсутcвии полей в B.
Re[2]: переоптимизировались?
От: BokiyIS  
Дата: 24.07.08 06:27
Оценка:
Здравствуйте, merk, Вы писали:

M>а попробуйте добавить в класс B переменную, чтобы он был непустой.

M>такое впечатление, что это переоптимизация. они видят, что у класса B нет собственных полей, и потому запуск конструктора считают излишним. а у А вообще нет конструктора, насколько я понимаю этот шарп.
M>если версия верна, то проблема в отсутcвии полей в B.

Даже если вы добавите поля в B, конструктор не запустится.
Re[4]: Странности наследования от абстрактного класса !!!
От: matumba  
Дата: 24.07.08 08:01
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>Эти вызовы -- забота VM, а не компилятора.


Не согласен. ВМ — это просто абстрактная машина с тупым набором инструкций, а сами инструкции — уже порождение "умного" (не всегда) компилятора.
И в данном случае, компилер обязан был вставить вызов конструктора класса В, а не А.
Re[5]: Странности наследования от абстрактного класса !!!
От: BokiyIS  
Дата: 24.07.08 08:03
Оценка:
Здравствуйте, matumba, Вы писали:

M>И в данном случае, компилер обязан был вставить вызов конструктора класса В, а не А.


Почему обязан?

Помимо статических локальных переменных, в компиляторах реализована и другая интересная функциональность. Как уже говорилось выше, CLR не поддерживает наследование статических членов. Тем не менее, компиляторы Visual Basic и C# позволяют обращаться к статическим членам базового типа по имени унаследованного типа.

Re[6]: Странности наследования от абстрактного класса !!!
От: matumba  
Дата: 24.07.08 09:04
Оценка:
Здравствуйте, BokiyIS, Вы писали:

BIS>Как уже говорилось выше, CLR не поддерживает наследование статических членов.


По идее, ООП, ФП, ЛП и прочее — это вообще не забота VM/CLR. Компилер генерит вызовы, ВМ их выполняет. Как получились эти вызовы — забота компилера (зависящая от языка).

BIS> Тем не менее, компиляторы Visual Basic и C# позволяют обращаться к статическим членам базового типа по имени унаследованного типа.


Это их собственные, внутренние проблемы. Есть элемент языка "статический конструктор". Точка. И пусть мелкософт хоть перепишет всю СЛРину, он ОБЯЗАН вызываться.
А иначе, чего ради все эти "фичи"?
Re[5]: Странности наследования от абстрактного класса !!!
От: Mab Россия http://shade.msu.ru/~mab
Дата: 24.07.08 10:36
Оценка: +1
Здравствуйте, matumba, Вы писали:

M>Не согласен. ВМ — это просто абстрактная машина с тупым набором инструкций,

От того, что ты с этим не согласен, реальность не поменяется. В .NET автоматическим запуском статических конструкторов занимается именно VM.
Re[6]: Странности наследования от абстрактного класса !!!
От: matumba  
Дата: 24.07.08 10:55
Оценка: :)
Здравствуйте, Mab, Вы писали:

Mab>От того, что ты с этим не согласен, реальность не поменяется. В .NET автоматическим запуском статических конструкторов занимается именно VM.


ХА! Тогда да, если ВМ сделана похмельными студентами, претензий нет. Но сама проблема осталась открытой — какого Х нужны в языке неработающие элементы?
Я ещё понимаю, ошибка компилера, но ВМ... это только в морг.
Спасибо, что вовремя просветили.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.