Qual è la differenza tra System.Type e System.RuntimeType in C #?


90

Oggi stavo cercando di eseguire alcuni test di convenzione e di ottenere tutti i tipi in un assembly (chiamando Assembly.GetTypes()), quando sono incappato in qualcosa:

System.RuntimeType:[First.Namespace.FirstClass]

Ogni volta che provo a confrontare quel tipo con typeof(FirstClass), non sono uguali. Quindi, quando provo a trovare tutti i tipi che contengono FirstClasscome parametro generico, non ne trovo nessuno.

Qual è la differenza tra System.RuntimeTypee System.Type?

C'è un modo per risolvere il mio problema?


6
Puoi fornire un piccolo programma che dimostri il problema che stai riscontrando?
Eric Lippert

Stavo per farlo, ma ho già ricevuto la risposta: P
Edgar Gonzalez

Risposte:


109

System.RuntimeTypeè una classe concreta che deriva dalla classe base astratta System.Type. Poiché System.RuntimeTypenon è pubblico, in genere incontrerai istanze di esso come System.Type.

Può sorgere confusione quando si tenta di ottenere il tipo di un oggetto e chiamare erroneamente GetType()un altro oggetto che rappresenta il tipo del primo oggetto, piuttosto che utilizzare direttamente quell'oggetto. Quindi Type.ToString()tornerà "System.RuntimeType"quando l'oggetto su cui è chiamato rappresenta un Tipo:

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

Ad esempio, in questo post del blog qualcuno sta cercando di ottenere il tipo di una colonna in un database, facendo qualcosa del genere:

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

Poiché val è già un oggetto Type, val.GetType () restituirà un altro oggetto Type che rappresenta il tipo System.RuntimeTimepoiché questo è il tipo concreto utilizzato per rappresentare l'oggetto di tipo originale. Il post del blog mostra quindi alcuni trucchi di riflessione non necessari, per ottenere il tipo dell'oggetto di tipo originale, quando in realtà tutto ciò che era richiesto era:

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

Quindi, se il tuo Typeoggetto sta segnalando che rappresenta a System.RuntimeType, assicurati di non aver chiamato accidentalmente GetType()un tipo che hai già.


Il primo frammento di codice controlla solo se l'oggetto è un'istanza di Type: restituirà true anche se lo passi typeof(int). Il secondo frammento di codice non funziona per il confronto typeof(string).GetType()e typeof(Type).
Mark Cidade

Questo e 'esattamente quello che stavo cercando! Ho trovato il post di Thomas Danecker ma non quello di Doogal Bell
Edgar Gonzalez

1
@Mark Cidade. Ben individuato, grazie. Ho risolto la risposta per essere più utile, sperando di chiarire qualsiasi confusione che ho introdotto citando quel post sul blog.
Ergwun

@Edgar Gonzalez: Quel post sul blog a cui ho fatto riferimento era in realtà piuttosto fuorviante. Si prega di consultare la mia risposta aggiornata per informazioni migliori.
Ergwun

4

Dalla risposta a Different between System.Type e System.RuntimeType di Thomas Danecker :

System.Type è una classe base astratta. Il CLR ha la sua implementazione concreta nel tipo interno System.RuntimeType. A causa di questo typeof (string) .GetType () restituisce un RuntimeType ma typeof (Type) restituisce un tipo normale. L'uso del metodo .Equals fa in effetti un object.ReferenceEquals che restituisce false. Per ottenere i risultati attesi, puoi usare type.IsInstanceOfType (element). Questo restituirà anche true se l'elemento è di un tipo derivato. Se desideri controllare il tipo esatto, il valore di ritorno false del tuo metodo è il risultato desiderato. È inoltre possibile utilizzare checkType (arrayType, Type.GetType ("System.RuntimeType")) per verificare la presenza di RuntimeType.


1
"fa in effetti un" - Possiamo ottenere una correzione grammaticale. Questo è il punto cruciale dell'intera faccenda e non ha senso.
N73k

2

In breve...

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

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

Il modo in cui ci penso ora è che System.Typeè un tipo di base per il tipo che rappresenta i risultati della richiesta del tipo di oggetto in fase di esecuzione, vale a dire System.RuntimeType. Così, quando si richiede il tipo di un oggetto, come in, "".GetType()l'istanza di System.Typerestituito è esso è discendente, System.RuntimeType. In effetti, ci si dovrebbe aspettare che typeof(System.Type).GetType()dovrebbe essere System.RuntimeTypecosì, ma penso che il framework prevenga specificamente questa ... simmetria.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.