79 votes

Les membres statiques d'une classe générique sont-ils liés à l'instance spécifique ?

Il s'agit davantage d'une documentation que d'une véritable question. Il semble qu'elle n'ait pas encore été abordée sur SO (à moins que je ne l'aie ratée), alors je vais la poser :

Imaginez une classe générique qui contient un membre statique :

class Foo<T> {
    public static int member;
}

Existe-t-il une nouvelle instance du membre pour chaque classe spécifique, ou bien une seule instance pour toutes les classes de type Foo- ?

Cela peut être facilement vérifié par un code comme celui-ci :

Foo<int>.member = 1;
Foo<string>.member = 2;
Console.WriteLine (Foo<int>.member);

Quel est le résultat, et où ce comportement est-il documenté ?

87voto

Fredrik Mörk Points 85694

A static est partagé par toutes les instances du même type . Foo<int> y Foo<string> sont de deux types différents. Ceci peut être prouvé par la ligne de code suivante :

// this prints "False"
Console.WriteLine(typeof(Foo<int>) == typeof(Foo<string>));

Quant à l'endroit où cela est documenté, on trouve ce qui suit dans la section 1.6.5 Champs de la spécification du langage C# (pour C# 3) :

Un champ statique identifie emplacement de stockage. [ ] d'instances d'une classe sont créées, il n'y a jamais qu'une seule copie d'un champ statique.

Comme indiqué précédemment ; Foo<int> y Foo<string> ne sont pas la même classe ; ce sont deux classes différentes construites à partir de la même classe générique. La façon dont cela se produit est décrite à la section 4.4 du document susmentionné :

Une déclaration de type générique dénote un type générique non lié qui qui est utilisé comme un "plan" pour former de nombreux types génériques. différents types, en appliquant des arguments de type.

16voto

SWeko Points 17524

Le problème ici est en fait le fait que les "classes génériques" ne sont pas des classes du tout.

Les définitions de classes génériques ne sont que des modèles de classes, et tant que leurs paramètres de type ne sont pas spécifiés, elles ne sont qu'un morceau de texte (ou une poignée d'octets).

Au moment de l'exécution, il est possible de spécifier un paramètre de type pour le modèle, lui donnant ainsi vie et créant une classe du type, maintenant entièrement spécifié. C'est pourquoi les propriétés statiques ne s'appliquent pas à l'ensemble du modèle, et c'est pourquoi il n'est pas possible d'effectuer un cast entre les propriétés statiques et les propriétés de type. List<string> y List<int> .

Cette relation reflète en quelque sorte la relation classe-objet. Tout comme les classes n'existent pas* tant que vous n'instanciez pas un objet à partir d'elles, les classes génériques n'existent pas tant que vous ne créez pas une classe basée sur le modèle.

P.S. Il est tout à fait possible de déclarer

class Foo<T> {
    public static T Member;
}

Il est évident que les membres statiques ne peuvent pas être partagés, car T est différent pour les différentes spécialisations.

4voto

ho1 Points 31752

Ils ne sont pas partagés. Je ne suis pas sûr de l'endroit où cela est documenté, mais un avertissement d'analyse. CA1000 ( Ne pas déclarer de membres statiques sur les types génériques ) met en garde contre cette pratique en raison du risque de rendre le code plus compliqué.

1voto

Marks Points 1369

Ils ne sont pas vraiment partagés. Parce que le membre n'appartient pas du tout à l'instance. Un membre de classe statique appartient à la classe elle-même. Ainsi, si vous avez MyClass.Number, il est le même pour tous les objets MyClass.Number car il ne dépend même pas de l'objet. Vous pouvez même appeler ou modifier MyClass.Number sans aucun objet.

Mais comme Foo< int > n'est pas la même classe que Foo< string >, ces deux nombres ne sont pas partagés.

Un exemple pour le montrer :

TestClass<string>.Number = 5;
TestClass<int>.Number = 3;

Console.WriteLine(TestClass<string>.Number);  //prints 5
Console.WriteLine(TestClass<int>.Number);     //prints 3

-3voto

Clement Herreman Points 5642

IMO, vous devez le tester, mais je pense que

Foo<int>.member = 1;
Foo<string>.member = 2;
Console.WriteLine (Foo<int>.member);

produira 1 parce que je pense que, pendant la compilation, le compilateur crée 1 classe pour chaque classe générique que vous utilisez (dans votre exemple : Foo<int> y Foo<string> ).

Mais je ne suis pas sûr à 100% =).

Remarque : Je pense que ce n'est pas une bonne conception ni une bonne pratique d'utiliser ce type d'attributs statiques.

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