所有 C# 泛型实例的静态成员变量是否通用?

Is a static member variable common for all C# generic instantiations?

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

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

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

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

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

我想澄清一下……

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


ECMA C# 语言规范的第 25.1.4 节

A static variable in a generic class declaration is shared amongst
all instances of the same closed constructed type (?§26.5.2), but is
not shared amongst instances of different closed constructed types.
These rules apply regardless of whether the type of the static
variable involves any type parameters or not.

您可能会看到这篇博文:Gus Perez 的泛型类中的静态字段

你也不能在 C# 中做到这一点。

1
MyGeneric.Variable = 1;

考虑以下来自 ECMA 语言规范的示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
2
MyGeneric<MyClass>.Variable
MyGeneric<MyOther>.Variable

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


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

本质上,运行时不会将开放类型视为正确的"类型"——只有封闭版本才是真正的类型。所以,MyGeneric<int>MyGeneric<string> 是两种完全不同的类型,因此有它们自己的静态变量实例。

因为你不能按照你建议的方式调用你的静态成员,这一点变得更加明显:MyGeneric.Variable 不会在 C# 中编译。

这个控制台应用程序代码很简单地说明了它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
}

不,它不共享。

对于 T.

的每种可能性,每个 MyGeneric<T> 类都将解析为不同的运行时类型

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


如上所述,您的问题的答案是否定的。但是,您可以做的是使用泛型类的父类,并在其中放置静态变量。您需要调用的任何方法都可以抽象到该父类中。

1
2
3
4
5
6
abstract class MyBase
{
    protected static MyBase selected;

    public abstract void Deselect();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyGeneric< T > : MyBase
{
    public void Select()
    {
        if (selected != null)
        {
            if (selected != this)
            {
                selected.Deselect();
            }
        }
        selected = this;
        //...
    }

    public override void Deselect()
    {
        //...
    }
}