15

在 C# 中,我有一个泛型类:

public class MyGeneric<ParameterClass> where ParameterClass: MyGenericParameterClass, new() {
    public static int Variable;
}

现在在 C++ 中,如果我用不同的参数实例化一个模板类,每个完整的类都会得到它自己的Variable,所以我不能说

MyGeneric.Variable = 1; // invalid in C++

在 C++ 中,但似乎我可以在 C# 中这样做。

我想澄清...

如果我有一个带有静态成员变量的泛型,该变量是否在所有泛型实例之间共享?

4

5 回答 5

17

ECMA C# 语言规范的第 25.1.4 节

泛型类声明中的静态变量在同一封闭构造类型(第 26.5.2 节)的所有实例之间共享,但在不同封闭构造类型的实例之间不共享。 无论静态变量的类型是否涉及任何类型参数,这些规则都适用。

您可能会看到这篇博文: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 
    }
}
于 2013-02-07T10:27:43.617 回答
7
MyGeneric<MyClass>.Variable
MyGeneric<MyOther>.Variable

这两个是不同的静态变量,被视为单独的类。

于 2013-02-07T10:23:01.773 回答
3

不它不是。泛型类型可以是“开放的”或“封闭的”。开放类型类似于List<T>未定义类型参数的类型。List<int>是封闭型。

本质上,运行时不会将开放类型视为正确的“类型” - 只有封闭版本才是真正的类型。所以,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;
}
于 2013-02-07T10:22:15.843 回答
2

不,它不共享。

对于. MyGeneric<T>_T

请检查静态成员是否没有非泛型MyGeneric类。Variable

于 2013-02-07T10:19:55.717 回答
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()
    {
        //...
    }
}
于 2021-02-26T11:02:09.347 回答