所有C#泛型实例都是常见的静态成员变量吗?

时间:2013-02-07 10:14:35

标签: c# generics static-variables

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

我想澄清......

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

5 个答案:

答案 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()
    {
        //...
    }
}