104 votes

.NET : Déterminer le type de la classe "this" dans sa méthode statique

Dans une méthode non statique, je pourrais utiliser this.GetType() et il retournerait le Type . Comment puis-je obtenir le même Type dans une méthode statique ? Bien sûr, je ne peux pas simplement écrire typeof(ThisTypeName) parce que ThisTypeName n'est connu qu'en cours d'exécution. Merci !

16 votes

Vous êtes dans un contexte STATIQUE et ne pouvez pas écrire typeof(ThisTypeName) ? Comment ?

1 votes

Il n'y a rien qui ressemble à un "runtime" à l'intérieur d'une méthode statique (en supposant que vous ne parlez pas d'un argument qui est passé à une méthode statique). Dans ce cas, vous pouvez simplement dire typeof(RelevantType) .

2 votes

Une méthode statique ne peut pas être virtuelle. Vous connaissez déjà le type.

145voto

JaredPar Points 333733

Si vous recherchez une doublure 1 qui équivaut à this.GetType() pour les méthodes statiques, essayez ce qui suit.

Type t = MethodBase.GetCurrentMethod().DeclaringType

Bien que cela soit probablement beaucoup plus coûteux que de simplement utiliser typeof(TheTypeName) .

1 votes

Celui-ci fonctionne bien. Merci :) Il n'est pas très cher car il sera appelé assez rarement.

2 votes

Entrase, par "coûteux", Jared entend qu'ils sont coûteux pour le processeur, ce qui signifie généralement qu'ils sont lents. Mais il a dit "beaucoup plus cher", ce qui signifie plus lent. Probablement pas lent du tout, sauf si vous concevez un système de guidage de fusée.

1 votes

J'ai vu GetCurrentMethod causer de sérieux problèmes de performance. Mais comme vous ne récupérez que le type, vous pouvez le mettre en cache.

59voto

Jon Skeet Points 692016

Il y a quelque chose que les autres réponses n'ont pas tout à fait clarifié, et qui est pertinent pour votre idée de type disponible uniquement au moment de l'exécution.

Si vous utilisez un type dérivé pour exécuter un membre statique, l'attribut réel Le nom du type est omis dans le binaire. Ainsi, par exemple, compilez ce code :

UnicodeEncoding.GetEncoding(0);

Maintenant utilisez ildasm dessus... vous verrez que l'appel est émis comme ceci :

IL_0002:  call       class [mscorlib]System.Text.Encoding 
[mscorlib]System.Text.Encoding::GetEncoding(int32)

Le compilateur a résolu l'appel à Encoding.GetEncoding - il n'y a aucune trace de UnicodeEncoding gauche. Cela rend votre idée de "type actuel" absurde, j'en ai peur.

0 votes

Avance rapide de 10 ans et pourquoi n'y a-t-il pas encore de statiques virtuelles en C# ? ;) en général, on n'en a pas besoin... mais il y a de rares occasions où elles sont utiles ;)

1 votes

@marchewek : Très, très rare je dirais - suffisamment rare pour que l'équipe C# ait toujours trouvé des choses plus utiles à faire. (Ce n'est pas comme s'ils étaient restés inactifs tout ce temps...)

0 votes

Je pense que c'est parce que le C# manque de fonctionnalités pour les classes statiques en général. Vous ne pouvez pas surcharger une méthode statique. Vous ne pouvez pas avoir de méthodes statiques ou de constructeurs dans une interface. Une partie de ces fonctionnalités peut être remplacée par la réflexion. Un exemple de cas est celui de la sérialisation. Avec une telle caractéristique comme les méthodes statiques dans l'interface, vous pouvez l'implémenter sans réflexion. L'obtention du type de classe à partir d'une méthode statique est utile pour déplacer le code d'initialisation partagé du singleton dans la classe de base. C'est le cas de "je ne sais pas si j'en avais besoin", je pense. Toutes ces approches sont utilisées en Objective-C/Swift.

27voto

Rob Leclerc Points 375

Une autre solution consiste à utiliser un type autoréférent

//My base class
//I add a type to my base class use that in the static method to check the type of the caller.
public class Parent<TSelfReferenceType>
{
    public static Type GetType()
    {
        return typeof(TSelfReferenceType);
    }
}

Puis dans la classe qui en hérite, je crée un type auto-référencé :

public class Child: Parent<Child>
{
}

Maintenant, l'appel de typeof(TSelfReferenceType) dans Parent obtiendra et retournera le type de l'appelant sans avoir besoin d'une instance.

Child.GetType();

-Rob

0 votes

Je l'ai utilisé pour les modèles de singleton, c'est-à-dire Singleton<T> ... les membres statiques peuvent alors faire référence à typeof(T) dans les messages d'erreur ou partout où cela est nécessaire.

2 votes

Bonjour, j'aime beaucoup et j'apprécie cette réponse car elle me donne une solution pour trouver le type enfant à partir d'une fonction de base statique.

1 votes

Joli coup. C'est dommage que cela ne puisse pas être fait en C# sans cette petite duplication de code, cependant.

5voto

John Feminella Points 116878

Vous ne pouvez pas utiliser this dans une méthode statique, donc ce n'est pas possible directement. Cependant, si vous avez besoin du type d'un objet, il suffit d'appeler GetType sur elle et faire le this instance un paramètre que vous devez passer, par exemple :

public class Car {
  public static void Drive(Car c) {
    Console.WriteLine("Driving a {0}", c.GetType());
  }
}

Cela semble être une mauvaise conception, cependant. Êtes-vous sûr que vous avez vraiment besoin d'obtenir le type de l'instance elle-même à l'intérieur de sa propre méthode statique ? Cela semble un peu bizarre. Pourquoi ne pas simplement utiliser une méthode d'instance ?

public class Car {
  public void Drive() { // Remove parameter; doesn't need to be static.
    Console.WriteLine("Driving a {0}", this.GetType());
  }
}

3voto

Tarydon Points 3358

Je ne comprends pas pourquoi vous ne pouvez pas utiliser typeof(ThisTypeName). Si c'est un type non générique, alors cela devrait fonctionner :

class Foo {
   static void Method1 () {
      Type t = typeof (Foo); // Can just hard code this
   }
}

Si c'est un type générique, alors :

class Foo<T> {
    static void Method1 () {
       Type t = typeof (Foo<T>);
    }
}

Est-ce que je rate quelque chose d'évident ici ?

7 votes

Cela ne fonctionnera pas si vous créez une classe Bar dérivée de Foo et qu'ensuite la classe hérite de Method1 - alors un appel à Bar.Method1 traitera toujours typeof(Foo) ce qui est faux. La Method1 héritée devrait d'une manière ou d'une autre savoir qu'elle est dérivée de Bar, et ensuite obtenir le typeof(Bar).

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