Was ist der Unterschied zwischen System.Type und System.RuntimeType in C #?

88

Ich habe heute versucht, einige Konventionstests durchzuführen und alle Typen in einer Assembly zu erhalten (durch Aufrufen Assembly.GetTypes()), als ich auf etwas gestoßen bin:

System.RuntimeType:[First.Namespace.FirstClass]

Wann immer ich versuche, diesen Typ mit zu vergleichen, typeof(FirstClass)sind sie nicht gleich. Wenn ich also versuche, alle Typen zu finden, die FirstClasseinen generischen Parameter enthalten, finde ich keine.

Was ist der Unterschied zwischen System.RuntimeTypeund System.Type?

Gibt es eine Möglichkeit, mein Problem zu lösen?

Edgar Gonzalez
quelle
6
Können Sie ein kleines Programm bereitstellen, das das aufgetretene Problem demonstriert?
Eric Lippert
Ich wollte, bekam aber schon die Antwort: P
Edgar Gonzalez

Antworten:

107

System.RuntimeTypeist eine konkrete Klasse, die sich von der abstrakten Basisklasse ableitet System.Type. Da System.RuntimeTypees nicht öffentlich ist, werden Sie normalerweise auf Instanzen davon als stoßen System.Type.

Verwirrung kann entstehen, wenn Sie versuchen, den Typ eines Objekts zu ermitteln und fälschlicherweise GetType()ein anderes Objekt aufrufen, das den Typ des ersten Objekts darstellt, anstatt nur dieses Objekt direkt zu verwenden. Dann Type.ToString()kehrt , "System.RuntimeType"wenn das Objekt , um es aufgerufen wird auf ist die eine Art:

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

In diesem Blog-Beitrag versucht beispielsweise jemand, den Typ einer Spalte in einer Datenbank abzurufen. Dabei wird Folgendes ausgeführt:

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

Da val bereits ein Typobjekt ist, gibt val.GetType () ein anderes Typobjekt zurück, das den Typ darstellt, System.RuntimeTimeda dies der konkrete Typ ist, der zur Darstellung des ursprünglichen Typobjekts verwendet wird . Der Blog-Beitrag zeigt dann einige unnötige Reflexionstricks, um den Typ des ursprünglichen Typobjekts zu ermitteln, wenn wirklich nur Folgendes erforderlich war:

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

Wenn Ihr TypeObjekt also meldet, dass es einen darstellt System.RuntimeType, stellen Sie sicher, dass Sie nicht versehentlich GetType()einen Typ aufgerufen haben, den Sie bereits haben.

Ergwun
quelle
Das erste Codefragment prüft nur, ob das Objekt eine Instanz von ist - es gibt Typetrue zurück, selbst wenn Sie übergeben typeof(int). Das zweite Code-Snippet funktioniert nicht zum Vergleichen von typeof(string).GetType()und typeof(Type).
Mark Cidade
Genau das habe ich gesucht! Ich habe Thomas Daneckers Beitrag gefunden, aber nicht Doogal Bells
Edgar Gonzalez
1
@ Mark Cidade. Gut gesehen, danke. Habe eine feste Antwort, um hilfreicher zu sein, und hoffentlich die Verwirrung zu beseitigen, die ich durch das Zitieren dieses Blogposts verursacht habe.
Ergwun
@ Edgar Gonzalez: Dieser Blog-Beitrag, auf den ich verwiesen habe, war eigentlich ziemlich irreführend. Weitere Informationen finden Sie in meiner aktualisierten Antwort.
Ergwun
4

Aus der Antwort auf Unterschied zwischen System.Type und System.RuntimeType von Thomas Danecker :

System.Type ist eine abstrakte Basisklasse. Die CLR hat ihre konkrete Implementierung im internen Typ System.RuntimeType. Aufgrund dieses Typs (Zeichenfolge) gibt .GetType () einen RuntimeType zurück, aber typeof (Typ) gibt einen normalen Typ zurück. Bei Verwendung der .Equals-Methode wird tatsächlich ein object.ReferenceEquals erstellt, das false zurückgibt. Um die erwarteten Ergebnisse zu erhalten, können Sie type.IsInstanceOfType (Element) verwenden. Dies gibt auch true zurück, wenn das Element vom abgeleiteten Typ ist. Wenn Sie nach dem genauen Typ suchen möchten, ist der Rückgabewert false Ihrer Methode das gewünschte Ergebnis. Sie können auch checkType (arrayType, Type.GetType ("System.RuntimeType")) verwenden, um nach dem RuntimeType zu suchen.

John Saunders
quelle
1
"tut tatsächlich ein" - Können wir eine Grammatikkorrektur bekommen? Das ist wie der Kern der ganzen Sache und es macht keinen Sinn.
N73k
2

In Kürze...

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

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

Ich denke jetzt, dass dies System.Typeein Basistyp für den Typ ist, der die Ergebnisse der Objekttypanforderung zur Laufzeit darstellt, nämlich System.RuntimeType. Wenn Sie also den Typ eines Objekts wie in anfordern, "".GetType()ist die zurückgegebene Instanz System.Typedessen Nachkommen System.RuntimeType. In der Tat sollte man erwarten, dass das auch so typeof(System.Type).GetType()sein sollte System.RuntimeType, aber ich denke, das Framework verhindert speziell diese ... Symmetrie.

George
quelle