C# 泛型类的静态成员是否绑定到特定实例?
这与其说是一个真正的问题,不如说是一个文档。这似乎还没有得到解决(除非我错过了),因此: 设想一个包含静态成员的泛型类:C# 泛型类的静态成员是否绑定到特定实例?,c#,.net,generics,static,C#,.net,Generics,Static,这与其说是一个真正的问题,不如说是一个文档。这似乎还没有得到解决(除非我错过了),因此: 设想一个包含静态成员的泛型类: class Foo<T> { public static int member; } class-Foo{ 公共静态int成员; } 每个特定类是否有一个新的成员实例,或者所有Foo类型类是否只有一个实例 可以很容易地通过以下代码进行验证: Foo<int>.member = 1; Foo<string>.member = 2;
class Foo<T> {
public static int member;
}
class-Foo{
公共静态int成员;
}
每个特定类是否有一个新的成员实例,或者所有Foo类型类是否只有一个实例
可以很容易地通过以下代码进行验证:
Foo<int>.member = 1;
Foo<string>.member = 2;
Console.WriteLine (Foo<int>.member);
Foo.member=1;
Foo.member=2;
Console.WriteLine(Foo.member);
结果是什么?这种行为记录在哪里?它们不是共享的。不确定它记录在哪里,但是分析警告(不要在泛型类型上声明静态成员)警告不要这样做,因为这样会使代码更加复杂。IMO,您需要测试它,但我认为
Foo<int>.member = 1;
Foo<string>.member = 2;
Console.WriteLine (Foo<int>.member);
Foo.member=1;
Foo.member=2;
Console.WriteLine(Foo.member);
将输出1
,因为我认为在编译期间,编译器会为您使用的每个泛型类创建一个类(在您的示例中:Foo
和Foo
)
但我不是100%肯定=)
备注:我认为使用此类静态属性既不是一个好的设计,也不是一个好的实践。a
static
字段在相同类型的所有实例中共享Foo
和Foo
是两种不同的类型。这可以通过以下代码行证明:
// this prints "False"
Console.WriteLine(typeof(Foo<int>) == typeof(Foo<string>));
//这会打印“False”
控制台写入线(typeof(Foo)==typeof(Foo));
关于记录的地方,在C语言规范(针对C#3)的第1.6.5节字段中可以找到以下内容:
静态字段正好标识一个
存储位置。不管有多少
创建类的实例,
一本书只有一本
静态场
如前所述Foo
和Foo
不是同一类;它们是由同一泛型类构造的两个不同类。上述文件第4.4节概述了这一过程:
泛型类型声明本身,
表示一个未绑定的泛型类型
被用作“蓝图”,形成许多
不同类型,通过应用
类型参数
它们不是真正共享的。 因为成员根本不属于实例。 静态类成员属于类本身。 因此,如果您有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
TestClass.Number=5;
TestClass.Number=3;
Console.WriteLine(TestClass.Number)//印刷品5
Console.WriteLine(TestClass.Number)//印刷品3
这里的问题实际上是“泛型类”根本不是类
泛型类定义只是类的模板,在指定其类型参数之前,它们只是一段文本(或少量字节)
在运行时,可以为模板指定一个类型参数,从而使其生效,并创建一个完全指定类型的类。这就是为什么静态属性不是全模板的,这就是为什么不能在List
和List
之间转换
这种关系有点像类-对象关系。就像类在实例化对象之前不存在一样,泛型类在基于模板创建类之前不存在
另外,很有可能申报
class Foo<T> {
public static T Member;
}
class-Foo{
公共静态T成员;
}
从静态角度看,静态成员不能共享,因为不同的专业T不同。泛型的
< P> C实现更接近C++。在这两种语言中,MyClass
和MyClass
不共享静态成员,但在Java中它们共享静态成员。在C++和C++<代码> MyClass < /C>中,在编译时,在内部创建全新类型,就像泛型是宏一样。您通常可以在堆栈跟踪中看到它们生成的名称,如MyClass'1
和MyClass'2
。这就是为什么它们不共享静态变量。在Java中,泛型是通过更简单的方法实现的,即编译器使用非泛型类型生成代码,并在所有地方添加类型转换。所以MyClass
和MyClass
不会在Java中生成两个全新的类,相反,它们下面都是相同的类MyClass
,这就是它们共享静态变量的原因。Wow,还有一条我在FX Cop上无法接受的规则。如果您同时使用C#和Java开发,这里记录了一个问题。虽然Foo
和Foo
在C#中是不同的类型,但它们在Java中是相同的类型,因为Java是如何处理泛型的(类型擦除/编译器技巧);foo1.成员=10;Foo foo2=新的Foo();foo2.member=20;这里发生了什么?@Everyone这两个实例的member值都将更改(并且将更改为20),因为它们共享相同的Foo类型。如果将具有静态成员的非泛型基类继承到派生泛型类中会怎么样?这还会是真的吗?@StasIvanov,foo1.member将保持10岁,foo2.member将保持20岁。请验证如果不是100%确定-不要评论简短回答:每个实际类都有一个新实例,即使用的t
每种类型都有一个(Foo
和Foo
代表两个不同的类,每个类都有一个实例,但是Foo
的多个实例将共享成员的一个实例). 有关更详细的示例,请参见: