Ещё раз... Написал абстрактный класс А с единственным членом — списком. Наследуясь от него создаю класс В, где статический конструктор добавляет в этот список один элемент. Потом в программе беру класс 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: Странности наследования от абстрактного класса !!!
Здравствуйте, Cynic, Вы писали:
C>Ещё раз... Написал абстрактный класс А с единственным членом — списком. Наследуясь от него создаю класс В, где статический конструктор добавляет в этот список один элемент. Потом в программе беру класс B, а список пуст Переношу объявление списка в класс B, все работает. Почему
В реальности используется A.strList поэтому, инициализации и не происходит.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Странности наследования от абстрактного класса !!!
Здравствуйте, 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: Странности наследования от абстрактного класса !!!
Здравствуйте, nikov, Вы писали:
N>Реализовать такое поведеение было бы затруднительно из-за того, что при компиляции стирается разница между обращением к статическому полую через базовый и производный классы.
Разница стирается в бинарном коде. Но компилятор-то знает, что было обращение к B.strList! Значит он должен перед этим вставить вызов B.B()
Или я что-то не догоняю?
Re[3]: Странности наследования от абстрактного класса !!!
Таким образом самым правильным было бы изменить последнюю строчку в приведенной цитате из 10.12 таким образом:
N>
N>• Any of the static members declared in the class type are referenced.
Т.е. в результате приходим к выводу, что статический конструктор класса вызывается только если в нем объявлен ссылочный член или создаётся экземпляр класса. Поэтому в данном случае вызывается только статический конструктор класса A, а не B. Я правильно понял
:)
Re[3]: Странности наследования от абстрактного класса !!!
Здравствуйте, Cynic, Вы писали:
C>Т.е. в результате приходим к выводу, что статический конструктор класса вызывается только если в нем объявлен ссылочный член или создаётся экземпляр класса. Поэтому в данном случае вызывается только статический конструктор класса A, а не B. Я правильно понял
Я не понимаю, что такое ссылочный член.
Поправка такая: надо заменить слова "обращение к статическому члену класса" на "обращение к статическому члену, определенному в этом классе".
Re[4]: Странности наследования от абстрактного класса !!!
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, Cynic, Вы писали:
C>>Т.е. в результате приходим к выводу, что статический конструктор класса вызывается только если в нем объявлен ссылочный член или создаётся экземпляр класса. Поэтому в данном случае вызывается только статический конструктор класса A, а не B. Я правильно понял
N>Я не понимаю, что такое ссылочный член.
Я имел ввиду, член ссылочного типа.
:)
Re[5]: Странности наследования от абстрактного класса !!!
Здравствуйте, 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]: Странности наследования от абстрактного класса !!!
Здравствуйте, 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]: Странности наследования от абстрактного класса !!!
Здравствуйте, Cynic, Вы писали:
C>Ещё раз... Написал абстрактный класс А с единственным членом — списком. Наследуясь от него создаю класс В, где статический конструктор добавляет в этот список один элемент. Потом в программе беру класс B, а список пуст Переношу объявление списка в класс B, все работает. Почему
а попробуйте добавить в класс B переменную, чтобы он был непустой.
такое впечатление, что это переоптимизация. они видят, что у класса B нет собственных полей, и потому запуск конструктора считают излишним. а у А вообще нет конструктора, насколько я понимаю этот шарп.
если версия верна, то проблема в отсутcвии полей в B.
Здравствуйте, merk, Вы писали:
M>а попробуйте добавить в класс B переменную, чтобы он был непустой. M>такое впечатление, что это переоптимизация. они видят, что у класса B нет собственных полей, и потому запуск конструктора считают излишним. а у А вообще нет конструктора, насколько я понимаю этот шарп. M>если версия верна, то проблема в отсутcвии полей в B.
Даже если вы добавите поля в B, конструктор не запустится.
Re[4]: Странности наследования от абстрактного класса !!!
Здравствуйте, Mab, Вы писали:
Mab>Эти вызовы -- забота VM, а не компилятора.
Не согласен. ВМ — это просто абстрактная машина с тупым набором инструкций, а сами инструкции — уже порождение "умного" (не всегда) компилятора.
И в данном случае, компилер обязан был вставить вызов конструктора класса В, а не А.
Re[5]: Странности наследования от абстрактного класса !!!
Здравствуйте, matumba, Вы писали:
M>И в данном случае, компилер обязан был вставить вызов конструктора класса В, а не А.
Почему обязан?
Помимо статических локальных переменных, в компиляторах реализована и другая интересная функциональность. Как уже говорилось выше, CLR не поддерживает наследование статических членов. Тем не менее, компиляторы Visual Basic и C# позволяют обращаться к статическим членам базового типа по имени унаследованного типа.
Re[6]: Странности наследования от абстрактного класса !!!
Здравствуйте, BokiyIS, Вы писали:
BIS>Как уже говорилось выше, CLR не поддерживает наследование статических членов.
По идее, ООП, ФП, ЛП и прочее — это вообще не забота VM/CLR. Компилер генерит вызовы, ВМ их выполняет. Как получились эти вызовы — забота компилера (зависящая от языка).
BIS> Тем не менее, компиляторы Visual Basic и C# позволяют обращаться к статическим членам базового типа по имени унаследованного типа.
Это их собственные, внутренние проблемы. Есть элемент языка "статический конструктор". Точка. И пусть мелкософт хоть перепишет всю СЛРину, он ОБЯЗАН вызываться.
А иначе, чего ради все эти "фичи"?
Re[5]: Странности наследования от абстрактного класса !!!
Здравствуйте, matumba, Вы писали:
M>Не согласен. ВМ — это просто абстрактная машина с тупым набором инструкций,
От того, что ты с этим не согласен, реальность не поменяется. В .NET автоматическим запуском статических конструкторов занимается именно VM.
Re[6]: Странности наследования от абстрактного класса !!!
Здравствуйте, Mab, Вы писали:
Mab>От того, что ты с этим не согласен, реальность не поменяется. В .NET автоматическим запуском статических конструкторов занимается именно VM.
ХА! Тогда да, если ВМ сделана похмельными студентами, претензий нет. Но сама проблема осталась открытой — какого Х нужны в языке неработающие элементы?
Я ещё понимаю, ошибка компилера, но ВМ... это только в морг.
Спасибо, что вовремя просветили.