在C#中,我有一个通用类:
public class MyGeneric<ParameterClass> where ParameterClass: MyGenericParameterClass, new() {
public static int Variable;
}
现在在C ++中如果我实例化一个带有不同参数的模板化类,每个完整的类都会得到它自己的Variable
,所以I just can't say
MyGeneric.Variable = 1; // invalid in C++
在C ++中,但似乎我可以在C#中这样做。
我想澄清......
如果我有一个带有静态成员变量的泛型,那么该变量是否在所有泛型实例之间共享?
答案 0 :(得分:13)
Section 25.1.4 of the ECMA C# Language specification
泛型类声明中的静态变量之间共享 相同封闭构造类型的所有实例(第26.5.2节),但是 不在不同的封闭构造类型的实例之间共享。 无论静态类型是否适用,这些规则都适用 变量涉及任何类型参数。
您可以在Static fields in generic classes
上看到此博文:Gus Perez你也不能在C#中做到这一点。
MyGeneric.Variable = 1;
请考虑ECMA语言规范中的以下示例。
class C<V>
{
static int count = 0;
public C()
{
count++;
}
public static int Count
{
get { return count; }
}
}
class Application
{
static void Main()
{
C<int> x1 = new C<int>();
Console.WriteLine(C<int>.Count); // Prints 1
C<double> x2 = new C<double>();
Console.WriteLine(C<double>.Count); // Prints 1
Console.WriteLine(C<int>.Count); // Prints 1
C<int> x3 = new C<int>();
Console.WriteLine(C<int>.Count); // Prints 2
}
}
答案 1 :(得分:6)
MyGeneric<MyClass>.Variable
MyGeneric<MyOther>.Variable
这两个不同的静态变量被视为单独的类。
答案 2 :(得分:2)
不,它不是共享的。
对于MyGeneric<T>
的每种可能性,每个T
类将解析为不同的运行时类型。
请检查没有MyGeneric
静态成员的非通用Variable
课程。
答案 3 :(得分:2)
不,不是。通用类型可以是“打开”或“关闭”。开放类型就像List<T>
之类,其中未定义类型参数; List<int>
是封闭式的。
实际上,运行时不会将open类型视为正确的“Type” - 只有封闭版本才是真正的类型。因此,MyGeneric<int>
和MyGeneric<string>
是两种完全不同的类型,因此拥有自己的静态变量实例。
由于无法以您建议的方式调用静态成员,因此更明显:MyGeneric.Variable
无法在C#中编译。
此控制台应用程序代码非常简单地说明了这一点:
class Program
{
static void Main(string[] args)
{
Test<int>.i = 2;
Test<string>.i = 8;
Console.WriteLine(Test<int>.i); // would write "8" if the fields were shared
Console.WriteLine(Test<string>.i);
// Console.WriteLine(Test.i); // does not compile
// Console.WriteLine(Test<>.i); // does not compile
}
}
class Test<T>
{
public static int i;
}
答案 4 :(得分:0)
如上所述,您的问题的答案是否定的。但是,您可以做的是使用泛型类的父类,并在其中放置静态变量。您需要调用的任何方法都可以抽象到该父类中。
abstract class MyBase
{
protected static MyBase selected;
public abstract void Deselect();
}
class MyGeneric<T> : MyBase
{
public void Select()
{
if (selected != null)
{
if (selected != this)
{
selected.Deselect();
}
}
selected = this;
//...
}
public override void Deselect()
{
//...
}
}