Come verificare se il tipo di variabile corrisponde al tipo memorizzato in una variabile


96
User u = new User();
Type t = typeof(User);

u is User -> returns true

u is t -> compilation error

Come posso verificare se qualche variabile è di qualche tipo in questo modo?

Risposte:


194

Le altre risposte contengono tutte omissioni significative.

L' isoperatore non controlla se il tipo di runtime dell'operando è esattamente il tipo dato; piuttosto, verifica se il tipo di runtime è compatibile con il tipo specificato:

class Animal {}
class Tiger : Animal {}
...
object x = new Tiger();
bool b1 = x is Tiger; // true
bool b2 = x is Animal; // true also! Every tiger is an animal.

Ma il controllo dell'identità del tipo con la riflessione controlla l' identità , non la compatibilità

bool b5 = x.GetType() == typeof(Tiger); // true
bool b6 = x.GetType() == typeof(Animal); // false! even though x is an animal

or with the type variable
bool b7 = t == typeof(Tiger); // true
bool b8 = t == typeof(Animal); // false! even though x is an 

Se non è quello che vuoi, probabilmente vuoi IsAssignableFrom:

bool b9 = typeof(Tiger).IsAssignableFrom(x.GetType()); // true
bool b10 = typeof(Animal).IsAssignableFrom(x.GetType()); // true! A variable of type Animal may be assigned a Tiger.

or with the type variable
bool b11 = t.IsAssignableFrom(x.GetType()); // true
bool b12 = t.IsAssignableFrom(x.GetType()); // true! A 

4
Sebbene l'approccio finale mostrato qui funzioni, è inutilmente prolisso. typeof(Animal).IsInstanceOfType(x)è più breve e più semplice di typeof(Animal).IsAssignableFrom(x.GetType());(e Resharper suggerirà di utilizzare il primo se utilizzi il secondo).
Mark Amery

PRECISAZIONE: per rispondere alla domanda iniziale, sostituire tper typeof(Animal). Quindi la forma migliorata di Mark diventa t.IsInstanceOfType(x).
ToolmakerSteve

13

GetType()esiste su ogni singolo tipo di framework, perché è definito sul objecttipo di base . Quindi, indipendentemente dal tipo stesso, puoi usarlo per restituire il sottostanteType

Quindi, tutto ciò che devi fare è:

u.GetType() == t

1
In realtà la risposta di Eric è utile e tutto, ma non risponde alla domanda effettiva su come eseguire il test con un tipo sconosciuto nel modo "u è t" descritto nella domanda originale, e il tuo lo fa.
Daniel

@Daniel - Non esattamente. La risposta di Dave è corretta solo se si desidera escludere sottoclassi di t. La risposta di Eric spiega principalmente cosa fare; manca solo il chiarimento su dove mettere "t". Aggiungerò un commento lì.
ToolmakerSteve

10

Devi vedere se il tipo della tua istanza è uguale al tipo della classe. Per ottenere il tipo di istanza si utilizza il GetType()metodo:

 u.GetType().Equals(t);

o

 u.GetType.Equals(typeof(User));

dovrebbe farlo. Ovviamente potresti usare '==' per fare il confronto se preferisci.


+1 Ma preferisci la seconda scelta. u.GetType.Equals(typeof(User));
Omar

Uno dei motivi per cui questo è meno sicuro rispetto all'utilizzo di == - è che se GetType () in qualche modo restituisce null - verrà lanciato.
Dave Bish

1
@Fuex, sì a me, penso che renda il codice più facile da leggere se il tipo di è inline, motivo per cui l'ho pubblicato in questo modo, anche se nell'esempio OP ha già una variabile tche contiene il tipo.
Sam Holder

@DaveBish se GetType restituisse un valore nullo, allora sarei preoccupato che un sacco di cose inizierebbero a gettare ... ma punto preso, hai ovviamente ragione
Sam Holder

@SamHolder Sì - L'unica situazione in cui ciò accadrebbe, sarebbe se qualcuno sovrascrisse un tipo di base e rovinasse l'implementazione in qualche modo. Sarebbe strano, di sicuro.
Dave Bish

4

Per verificare se un oggetto è compatibile con una data variabile di tipo, invece di scrivere

u is t

dovresti scrivere

typeof(t).IsInstanceOfType(u)

1
Qual è il vantaggio della sintassi più dettagliata rispetto alla sintassi "u is t"?
Kyle Humfeld

@KyleHumfeld Se avessi Type foo; Oggetto A; non puoi scrivere "A is foo", ma puoi scrivere foo.isInstanceOfType (A)
Timur Nuriyasov
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.