28 votes

Pourquoi ne pas statique de la variable d'incrémentation lors de l'utilisation de médicaments génériques?

J'ai besoin d'une certaine classe de contenir un membre statique qui garde la trace de chaque fois qu'une instance de cette classe est instanciée, essentiellement, de sorte que chaque instance de la classe a un index unique. Il fonctionne avec un non-classe générique, mais ce générique de la mise en œuvre échoue à chaque fois que le type T diffère entre les instances:

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>(); 
    }
}

La sortie est:

1

2

3

1

Dès que le type T des commutateurs de type int au lieu de string, le compteur est remis à zéro.

Est-ce à l'échec de par leur conception, et si oui, quelle est la raison, ou comment puis-je obtenir autour d'elle? Ou est-ce un bug? Elle donne un sens à un certain degré, car le type T, étant générique, est dans la déclaration de classe, mais..

32voto

Enigmativity Points 26345

Chaque T crée une nouvelle classe pour l' A<T> et donc distinctes statique compteurs.

Pour contourner ce problème, vous pouvez utiliser l'héritage de la sorte:

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);      
   }
}

26voto

Oded Points 271275

Pas un bug c'est par la conception, et est une conséquence de la manière dont les génériques de travail.

Un type générique comme votre A<T> sert de modèle - lorsque vous utilisez les paramètres de type, le compilateur génère une classe réelle avec ce type (cette classe est réutilisé, mais un autre sera créé pour chaque type différent).

C'est ce qui explique les résultats que vous voyez - là est un champ statique pour l' A<int> et une pour l' A<string>.

10voto

sll Points 30638

C'est parce que les différents types de sont générés sous le capot pour les classes avec différents paramètres de type générique. Cette différence est uniquement pour le type de la valeur des paramètres, comme de bien vouloir noter par Ben dans le commentaire.

Découvrez ces articles MSDN:

EDIT:

Envisager de code suivant:

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
    }
}

7voto

Hand-E-Food Points 5510

Une classe générique est un modèle dont les autres classes sont créées. Un List<String> et List<int> sont deux choses complètement différentes classes, malgré tous deux originaires de List<T>.

Votre classes génériques référence à un non-générique de la classe qui détient le comptoir. Ne mettez pas la classe statique à l'intérieur de la classe générique. Ce sera la cause de la statique de la classe doit être généré pour chaque valeur de 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++;
    }
}

5voto

drdwilcox Points 2970

Les génériques avec différents paramètres de type de type différent. Donc, A<int> et A<string> sont des classes différentes, et sont donc alloués différents statique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X