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

Posted

技术标签:

【中文标题】所有 C# 泛型实例的静态成员变量是不是通用?【英文标题】:Is a static member variable common for all C# generic instantiations?所有 C# 泛型实例的静态成员变量是否通用? 【发布时间】:2013-01-22 19:15:10 【问题描述】:

在 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# 中这样做。

我想澄清一下...

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

【问题讨论】:

【参考方案1】:

Section 25.1.4 of the ECMA C# Language specification

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

您可能会看到这篇博文:Static fields in generic classesGus 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 
    

【讨论】:

【参考方案2】:
MyGeneric<MyClass>.Variable
MyGeneric<MyOther>.Variable

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

【讨论】:

【参考方案3】:

不,不是。泛型类型可以是“开放的”或“封闭的”。开放类型类似于List&lt;T&gt;,其中未定义类型参数; List&lt;int&gt; 是封闭类型。

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

不能以您建议的方式调用静态成员这一事实使这一点变得更加明显: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】:

不,不共享。

对于T 的每种可能性,每个MyGeneric&lt;T&gt; 类都将解析为不同的运行时类型。

请检查不存在具有Variable 静态成员的非泛型MyGeneric 类。

【讨论】:

【参考方案5】:

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

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()
    
        //...
    

【讨论】:

以上是关于所有 C# 泛型实例的静态成员变量是不是通用?的主要内容,如果未能解决你的问题,请参考以下文章

c# 中的泛型 & 访问 T 的静态成员

静态方法与实例方法

c# 泛型的静态成员

c# 泛型的静态成员

c# 泛型的静态成员

C#基础——静态成员,static关键字