2015-05-29 8 views
9

un'occhiata al codice di esempioActivator.CreateInstance crea valore di tipo T, invece di Nullable <T>

var genericNullableType = typeof(Nullable<>); 
var nullableType = genericNullableType.MakeGenericType(typeof(bool)); 
var returnValue = Activator.CreateInstance(nullableType, (object)false); 

Per qualche motivo variabile returnValue sarà di tipo bool e non bool?. Perché è così e come potrebbe essere evitato?

UPD: Ecco uno screenshot dal mio VS enter image description here

+0

@petelids Sto usando VS 2013 Premium e .NET Framework 4.5 e la configurazione di build è Debug. Usi la stessa configurazione? – Demarsch

+1

Questo non è esclusivo di "Attivatore". 'Console.WriteLine ((new Nullable (false) .GetType(). FullName));' anche sputa semplicemente Boolean. – vcsjones

+1

Non c'è modo di ottenere un valore nullo in box. Il runtime ha una gestione speciale per il box nullable e lo scaccherà sempre in un valore in box del tipo sottostante o un riferimento null. Detto questo dovrebbe essere considerato un bool? Quindi non sono sicuro di cosa stai cercando. –

risposta

15

In questo caso particolare che si sta utilizzando il sovraccarico di CreateInstance che restituisce object. Il Nullable<T> è un struct quindi deve essere rappresentato come object che avrebbe dovuto essere in scatola. Tuttavia, lo Nullable<T> non può essere effettivamente inserito nelle regole del CLR. Viene invece utilizzato il valore sottostante o null. Questo è il motivo per cui si ottiene un raw bool invece di bool?.

Documentation: https://msdn.microsoft.com/en-us/library/ms228597.aspx

EDIT

Sembra che ci sia una certa confusione intorno determinare se il tipo di un valore Null oppure no. In particolare è stato sottolineato che le seguenti stampe System.Boolean e non System.Nullable``1[System.Boolean]:

var x = (bool?)true; 
Console.WriteLine(x.GetType()); 

Questo codice è anche cadere preda alla boxe. La chiamata a GetType ha un funzionamento boxe implicita perché è un'invocazione di un metodo virtuale su object, non un metodo su Nullable<T>:

IL_0009: ldloc.0 
IL_000a: box valuetype [mscorlib]System.Nullable`1<bool> 
IL_000f: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType() 
IL_0014: call void [mscorlib]System.Console::WriteLine(object) 

Il modo più sicuro per stampare il tipo effettivo di un valore var è fare la seguente trucco con generici:

static void PrintType<T>(T value) 
{ 
    Console.WriteLine(typeof(T)); 
} 

PrintType(x); // Prints System.Nullable`1[System.Boolean] 
+0

Anche se un altro è stato utilizzato il sovraccarico di CreateInstance, GetType sarebbe ancora internamente box perché non è virtuale, quindi non vedresti mai un 'Nullable ' da GetType, corretto? –

+0

@mikez corretto. La chiamata a 'GetType()' genera un codice implicito '.box' il che impedisce di sputare il tipo nullable. Per ottenere il tipo corretto da stampare, è necessario utilizzare i generici. Lo dimostrerò in un solo secondo. – JaredPar

Problemi correlati