generics类的静态成员是否与特定实例绑定?
这更像是一个文档,而不是一个真正的问题。 这似乎还没有在SO上解决(除非我错过了),所以在这里:
设想一个包含静态成员的generics类:
class Foo<T> { public static int member; }
是否有每个特定类的成员的新实例,或者是否只有一个Foo-type类的实例?
它可以很容易地被这样的代码validation:
Foo<int>.member = 1; Foo<string>.member = 2; Console.WriteLine (Foo<int>.member);
结果是什么,这种行为在哪里logging?
static
字段在同一types的所有实例中共享。 Foo<int>
和Foo<string>
是两种不同的types。 这可以通过下面的代码行来certificate:
// this prints "False" Console.WriteLine(typeof(Foo<int>) == typeof(Foo<string>));
至于在哪里有文档记载,可以在1.6.5节C#语言规范的字段 (对于C#3)中find以下内容:
一个静态字段确切地标识一个存储位置。 无论创build多less个实例,只有一个静态字段的副本。
如前所述; Foo<int>
和Foo<string>
不是同一个类; 它们是由同一个generics类构造的两个不同的类。 上述文件的第4.4节概述了这种情况:
genericstypes声明本身表示一个未绑定的genericstypes,通过应用types参数,用作“蓝图”来形成许多不同的types。
这里的问题实际上是“通用类”根本不是类。
generics类定义只是类的模板,直到指定了它们的types参数,它们只是一段文本(或几个字节)。
在运行时,可以为模板指定一个types参数,从而使其生效,并创build一个现在完全指定types的类。 这就是为什么静态属性不是模板范围的,这就是为什么你不能在List<string>
和List<int>
。
这种关系反映了类与对象的关系。 就像类不存在直到你从它们实例化一个对象,generics类不存在,直到你根据模板创build一个类。
PS这是很有可能宣布
class Foo<T> { public static T Member; }
由此可见,静态成员不能共享,因为不同专业的T是不同的。
他们不共享。 不知道它在哪里被logging,但分析警告CA1000 ( 不要在genericstypes上声明静态成员 )因为使代码更复杂的风险而提出警告。
generics的C#实现更接近于C ++。 在这两种语言中, MyClass<Foo>
和MyClass<Bar>
不共享静态成员,但在Java中它们是共享的。 在C#和C ++中, MyClass<Foo>
在编译时内部创build全新的types,就像generics是一种macros一样。 您通常可以在堆栈跟踪中看到他们生成的名称,如MyClass'1
和MyClass'2
。 这就是为什么他们不共享静态variables。 在Java中,generics是通过使用非genericstypes的编译器生成代码更简单的方法来实现的,并添加了types转换。 因此, MyClass<Foo>
和MyClass<Bar>
不会在Java中生成两个全新的类,而是它们都是同一个类MyClass
,这就是它们共享静态variables的原因。
他们并不真正分享。 因为该成员根本不属于该实例。 静态类成员属于类本身。 所以,如果你有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
国际海事组织,你需要testing它,但我认为
Foo<int>.member = 1; Foo<string>.member = 2; Console.WriteLine (Foo<int>.member);
将输出1
因为我认为,在编译期间,编译器为您使用的每个generics类(例如: Foo<int>
和Foo<string>
)创build一个类。
但我不是100%肯定=)。
备注:我认为使用这种静态属性并不是一个好的devise,也不是一个好习惯。