Quelle est la différence entre System.Type et System.RuntimeType en C #?

89

J'essayais de faire des tests de convention aujourd'hui, et d'obtenir tous les types dans un assembly (en appelant Assembly.GetTypes()), quand je suis tombé sur quelque chose:

System.RuntimeType:[First.Namespace.FirstClass]

Chaque fois que j'essaie de comparer ce type avec typeof(FirstClass), ils ne sont pas égaux. Donc, quand j'essaye de trouver tous les types qui contiennent FirstClasscomme paramètre générique, je n'en trouve aucun.

Quelle est la différence entre System.RuntimeTypeet System.Type?

Existe-t-il un moyen de résoudre mon problème?

Edgar Gonzalez
la source
6
Pouvez-vous fournir un petit programme illustrant le problème que vous rencontrez?
Eric Lippert
J'allais, mais j'ai déjà eu la réponse: P
Edgar Gonzalez

Réponses:

108

System.RuntimeTypeest une classe concrète qui dérive de la classe de base abstraite System.Type. Puisqu'il System.RuntimeTypen'est pas public, vous en rencontrerez généralement des instances comme System.Type.

Une confusion peut survenir lorsque vous essayez d'obtenir le type d'un objet et que vous appelez par erreur GetType()un autre objet représentant le type du premier objet, plutôt que de simplement utiliser cet objet directement. Puis Type.ToString()retournera "System.RuntimeType"lorsque l'objet sur lequel il est appelé représente un Type:

string str = string.Empty;
Type strType = str.GetType();
Type strTypeType = strType.GetType();
strType.ToString();     // returns "System.string"
strTypeType.ToString(); // returns "System.RuntimeType"

Par exemple, dans ce billet de blog, quelqu'un essaie d'obtenir le type d'une colonne dans une base de données, en faisant quelque chose comme ceci:

object val = reader.GetFieldType(index);
Type runtimeType = val.GetType();
PropertyInfo propInfo = runtimeType.GetProperty("UnderlyingSystemType");
Type type = (Type)propInfo.GetValue(val, null);

Puisque val est déjà un objet Type, val.GetType () retournera un autre objet Type représentant le type System.RuntimeTimecar il s'agit du type concret utilisé pour représenter l'objet type d'origine. Le billet de blog montre ensuite une supercherie de réflexion inutile, pour obtenir le type de l'objet de type d'origine, alors qu'en réalité, tout ce qui était nécessaire était:

Type type = reader.GetFieldType(index) as Type;

Donc, si votre Typeobjet signale qu'il représente a System.RuntimeType, assurez-vous que vous n'avez pas accidentellement appelé GetType()un type que vous avez déjà.

Ergwun
la source
Le premier extrait de code vérifie uniquement si l'objet est une instance de Type—il retournera vrai même si vous réussissez typeof(int). Le deuxième extrait de code ne fonctionne pas pour comparer typeof(string).GetType()et typeof(Type).
Mark Cidade
Ceci est exactement ce que je cherchais! J'ai trouvé le message de Thomas Danecker mais pas celui de Doogal Bell
Edgar Gonzalez
1
@Mark Cidade. Bien repéré, merci. Avoir une réponse fixe pour être plus utile, en espérant dissiper toute confusion que j'ai introduite en citant cet article de blog.
Ergwun
@Edgar Gonzalez: Ce billet de blog auquel j'ai fait référence était en fait plutôt trompeur. Veuillez consulter ma réponse mise à jour pour de meilleures informations.
Ergwun
4

De la réponse à Différent entre System.Type et System.RuntimeType par Thomas Danecker :

System.Type est une classe de base abstraite. Le CLR a son implémentation concrète dans le type interne System.RuntimeType. En raison de ce typeof (chaîne) .GetType () renvoie un RuntimeType mais typeof (Type) renvoie un type normal. L'utilisation de la méthode .Equals fait en fait un object.ReferenceEquals qui renvoie false. Pour obtenir les résultats attendus, vous pouvez utiliser type.IsInstanceOfType (élément). Cela retournera également true si l'élément est d'un type dérivé. Si vous souhaitez vérifier le type exact, la valeur de retour false de votre méthode est le résultat souhaité. Vous pouvez également utiliser checkType (arrayType, Type.GetType ("System.RuntimeType")) pour vérifier le RuntimeType.

John Saunders
la source
1
"fait en fait un" - Pouvons-nous obtenir une correction grammaticale. C'est comme le nœud de tout cela et cela n'a pas de sens.
N73k
2

En bref...

    "".GetType().ToString()           == "System.String"

    "".GetType().GetType().ToString() == "System.RuntimeType"

La façon dont je pense maintenant est qu'il System.Types'agit d'un type de base pour le type qui représente les résultats de la demande de type d'objet au moment de l'exécution, à savoir System.RuntimeType. Ainsi, lorsque vous demandez le type d'un objet, comme dans "".GetType(), l'instance deSystem.Type retour est descendant de lui, System.RuntimeType. En fait, il faut s'attendre à ce que le typeof(System.Type).GetType()soit System.RuntimeTypeaussi, mais je pense que le cadre empêche spécifiquement cette ... symétrie.

George
la source