为什么这个静态变量在使用泛型时不增加?

本文关键字:泛型 增加 静态 变量 为什么 | 更新日期: 2023-09-27 18:14:50

我需要一个特定的类来包含一个静态成员,该成员跟踪该类实例的每次实例化,本质上是为了使该类的每个实例都有一个唯一的索引。它适用于非泛型类,但当实例之间的类型T不同时,这种泛型实现就会失败:

class A<T>
{
   private static int counter;
   private static int Counter {
       get { 
          Increment(); 
          return counter; 
       }
   }
   private static void Increment() {
       counter++; 
   }
   public int Index; 
   public A()
   {
       this.Index = Counter; // using A<T>.Counter makes no difference
       Console.WriteLine(this.Index);      
   }
}

class Program
{
    static void Main(string[] args)
    {
        var a = new A<string>();
        var b = new A<string>(); 
        var c = new A<string>();
        var d = new A<int>(); 
    }
}

输出为:

1

2

3

1

一旦类型T切换为int而不是string,计数器就会重置。

这是设计失败的吗?如果是,原因是什么?我该如何解决?还是一个bug?这在某种程度上是有意义的,因为类型T是泛型的,在类声明中,但是。

为什么这个静态变量在使用泛型时不增加?

每个不同的TA<T>创建一个新类,因此不同的静态计数器

要解决这个问题,你可以像这样使用继承:
abstract class A
{
   protected static int counter;
}
class A<T> : A
{
   private static int Counter {
       get { 
          Increment(); 
          return counter; 
       }
   }
   private static void Increment() {
       counter++; 
   }
   public int Index; 
   public A()
   {
       this.Index = Counter;
       Console.WriteLine(this.Index);      
   }
}

不是bug——这是设计的结果,是泛型工作方式的结果。

A<T>这样的泛型作为模板-当你使用类型参数时,编译器会生成一个实际的T类型的类,并且会为每个不同类型的T创建一个不同的类。

这解释了您看到的结果——A<int>有一个静态字段,A<string>有另一个静态字段。

这是因为具有不同泛型类型参数的类在底层生成了不同的类型。正如Ben在注释中善意指出的那样,这种差异仅适用于值类型参数。

查看这些MSDN文章:

  • 运行时泛型
  • 反射类型和泛型类型

编辑:

考虑以下代码:

public abstract class GenericBase<T>
{
    public static int Counter { get; set; }        
}
public class GenericInt : GenericBase<int>
{        
}
public class GenericLong : GenericBase<long>
{        
}
public class GenericDecimal : GenericBase<decimal>
{        
}
[TestFixture]
public class GenericsTests
{
    [Test]
    public void StaticContextValueTypeTest()
    {
        GenericDecimal.Counter = 10;
        GenericInt.Counter = 1;
        GenericLong.Counter = 100;
       // !! At this point value of the Counter property
       // in all three types will be different - so does not shared across
       // all types
    }
}

泛型类是创建其他类的模板。List<String>List<int>是两个完全不同的类,尽管它们都起源于List<T>

让泛型类引用保存计数器的非泛型类。不要将静态类放在泛型类中。这将导致为T的每个值生成静态类。

class A<T>
{
    private static int Counter {
        get {
            ACounter.Increment();
            return ACounter.counter;
        }
    }
    public int Index;
    public A()
    {
       this.Index = Counter;
       Console.WriteLine(this.Index);
    }
}
static class ACounter
{
    static ACounter() {
        counter = 0;
    }
    public static int counter {get; private set;};
    public static void Increment() {
        counter++;
    }
}
具有不同类型参数的泛型是不同的类型。所以A<int>A<string>是不同的类,所以分配了不同的静态量

这是设计。A<int>的实例不是A<string>的实例,它们是不同的类,所以每个类有两个静态变量。

A<int>实际上与A<string>是一个不同的类,因此它们有不同的静态计数器

这就是Resharper在泛型中标记静态变量的原因,因为似乎很少有程序员理解静态变量,尤其是泛型中的静态变量