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