Это - больше документации, чем реальный вопрос. Это, кажется еще, не было обращено на ПОЭТОМУ (если я не пропустил его), таким образом, здесь идет:
Вообразите универсальный класс, который содержит статического участника:
class Foo<T> {
public static int member;
}
Существует ли новый экземпляр участника для каждого определенного класса, или существует ли только единственный экземпляр для всех классов типа Нечто?
Это может легко быть проверено кодом как это:
Foo<int>.member = 1;
Foo<string>.member = 2;
Console.WriteLine (Foo<int>.member);
Каков результат, и где это поведение документируется?
Статическое поле
совместно используется всеми экземплярами одного типа . Foo
и Foo
- это два разных типа. Это может быть доказано следующей строкой кода:
// this prints "False"
Console.WriteLine(typeof(Foo<int>) == typeof(Foo<string>));
Что касается того, где это задокументировано, следующее можно найти в разделе 1.6.5 Поля спецификации языка C # (для C # 3):
Статическое поле идентифицирует ровно один место хранения. Независимо от того, сколько создаются экземпляры класса, есть только одна копия статическое поле.
Как указывалось ранее; Foo
и Foo
не являются одним и тем же классом; это два разных класса, построенные из одного и того же универсального класса. Как это происходит, описано в разделе 4.4 вышеупомянутого документа:
Само по себе объявление общего типа, обозначает несвязанный универсальный тип, который используется как «план» для формирования многих разные виды, в порядке применения аргументы типа.
IMO, вам нужно проверить это, но я думаю, что
Foo<int>.member = 1;
Foo<string>.member = 2;
Console.WriteLine (Foo<int>.member);
выведет 1
, потому что я думаю, что во время компиляции компилятор создает 1 класс для каждого общего класса, который вы используете (в вашем примере : Foo
и Foo
).
Но я не уверен на 100% =).
Примечание: я считаю, что использование статических атрибутов такого типа - плохой дизайн и плохая практика.
Проблема здесь в том, что «универсальные классы» вообще не являются классами.
Определения универсальных классов - это просто шаблоны для классов, и до тех пор, пока не будут указаны их параметры типа, они будут просто фрагментом текста (или горсткой байтов).
Во время выполнения можно указать параметр типа для шаблона, тем самым оживив его и создав класс теперь уже полностью определенного типа. Вот почему статические свойства не являются общими для всего шаблона, и поэтому вы не можете использовать приведение между List
и List
.
Эти отношения как бы отражают отношения класса и объекта. Так же, как классы не существуют * до тех пор, пока вы не создадите из них экземпляр объекта, универсальные классы не существуют, пока вы не создадите класс на основе шаблона.
P.S. Вполне возможно объявить
class Foo<T> {
public static T Member;
}
. Отсюда очевидно, что статические члены не могут быть общими, поскольку T различается для разных специализаций.
На самом деле они не являются общими. Потому что член вообще не принадлежит экземпляру. Статический член класса принадлежит самому классу. Итак, если у вас есть MyClass.Number, он одинаков для всех объектов MyClass.Number, потому что он даже не зависит от объекта. Вы даже можете вызвать или изменить MyClass.Number без какого-либо объекта.
Но поскольку Foo
Пример, показывающий это:
TestClass<string>.Number = 5;
TestClass<int>.Number = 3;
Console.WriteLine(TestClass<string>.Number); //prints 5
Console.WriteLine(TestClass<int>.Number); //prints 3
Они не являются общими. Не уверен, где это задокументировано, но предупреждение анализа CA1000 ( Не объявляйте статические члены в универсальных типах ) предупреждает только об этом из-за риска усложнения кода.