【问题标题】: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# 中这样做。

我想澄清一下...

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

【问题讨论】:

    标签: c# generics static-variables


    【解决方案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()
                {
                    //...
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-03-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多