2011-09-28 12 views
38

Ho un comportamento del metodo generico che dipende da T è il tipo di riferimento o il tipo di valore. Sembra così:Come determinare se T è un tipo di valore o una classe di riferimento in generale?

T SomeGenericMethod <T> (T obj) 
{ 
    if (T is class) //What condition I must write in the brackets? 
    //to do one stuff 
    else //if T is a value type like struct, int, enum and etc. 
    //to do another stuff 
} 

Non posso duplicare questo metodo come:

T SomeGenericMethod <T> (T obj) where T : class 
{ 
//Do one stuff 
} 

T SomeGenericMethod <T> (T obj) where T : struct 
{ 
//Do another stuff 
} 

perché le loro firme sono uguali. Qualcuno può aiutarmi?

risposta

62

È possibile utilizzare il typeof operator con tipi generici, così typeof(T) otterrà il riferimento Type corrispondente a T, e quindi utilizzare il IsValueType proprietà:

if (typeof(T).IsValueType) 

Oppure, se si desidera includere i tipi di valore nullable come se ci re reference types:

// Only true if T is a reference type or nullable value type 
if (default(T) == null) 
+1

Grazie per la spiegazione aggiuntiva sui tipi di valori nullable. – mkus

+0

La seconda opzione è un possibile confronto di un tipo di valore con null, che è qualcosa su cui ReSharper piace abbaiare. C'è un modo per aggirare questo? – bubbleking

+0

@bubbleking: dipende da cosa stai cercando di ottenere, davvero ... –

6

Type.IsValueType indica, naturalmente, se Type è un tipo di valore. Quindi, typeof(T).IsValueType.

6

[La risposta che segue non controlla il tipo statica del T ma il tipo di objdinamica. Questo non esattamente è quello che hai chiesto, ma dal momento che potrebbe essere utile per il vostro problema in ogni caso, io terrò questa risposta per riferimento.]

Tutti i tipi di valore (e solo quelli) derivano da System.ValueType. Pertanto, la seguente condizione può essere utilizzato:

if (obj is ValueType) { 
    ... 
} else { 
    ... 
} 
+0

T è un tipo, non un'espressione, quindi non è possibile utilizzare 'is'. Inoltre, considera dove 'T' è esattamente System.ValueType, che è un tipo di riferimento ... –

+0

@JonSkeet: Grazie, buon punto, cambiato in' obj is ValueType'. Poiché 'ValueType' è una classe astratta,' obj' non può essere esattamente 'ValueType' (ovviamente, questo presuppone che' obj' non sia nullo ... Lo aggiungo alla mia risposta). – Heinzi

+0

Questo non ti dice di 'T'. Consideriamo 'SomeGenericMethod (null)' - 'int?' È un tipo di valore, ma la condizione non corrisponde. –

4

provate questo:

if (typeof(T).IsValueType) 
Problemi correlati