Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 泛型类的静态成员是否绑定到特定实例?_C#_.net_Generics_Static - Fatal编程技术网

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与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
的多个实例将共享
成员的一个实例). 有关更详细的示例,请参见: