Come posso convertire un System.Type nella sua versione nullable?

Ancora una volta uno di questi: “C’è un modo più semplice di fare le cose al posto del mio metodo di supporto?”

Quindi è facile ottenere il tipo sottostante da un tipo nullable, ma come faccio a ottenere la versione nullable di un tipo .NET?

Quindi ho

typeof(int) typeof(DateTime) System.Type t = something; 

e io voglio

 int? DateTime? 

o

 Nullable (which is the same) if (t is primitive) then Nullable else just T 

Esiste un metodo integrato?

Ecco il codice che uso:

 Type GetNullableType(Type type) { // Use Nullable.GetUnderlyingType() to remove the Nullable wrapper if type is already nullable. type = Nullable.GetUnderlyingType(type); if (type.IsValueType) return typeof(Nullable<>).MakeGenericType(type); else return type; } 

Ho un paio di metodi che ho scritto nella mia libreria di utilità su cui ho fatto molto affidamento. Il primo è un metodo che converte qualsiasi tipo nel suo modulo Nullable corrispondente:

  ///  /// [ public static Type GetNullableType(Type TypeToConvert) ] ///  /// Convert any Type to its Nullable<T> form, if possible ///  /// The Type to convert ///  /// The Nullable<T> converted from the original type, the original type if it was already nullable, or null /// if either  could not be converted or if it was null. ///  ///  /// To qualify to be converted to a nullable form,  must contain a non-nullable value /// type other than System.Void. Otherwise, this method will return a null. ///  ///  public static Type GetNullableType(Type TypeToConvert) { // Abort if no type supplied if (TypeToConvert == null) return null; // If the given type is already nullable, just return it if (IsTypeNullable(TypeToConvert)) return TypeToConvert; // If the type is a ValueType and is not System.Void, convert it to a Nullable if (TypeToConvert.IsValueType && TypeToConvert != typeof(void)) return typeof(Nullable<>).MakeGenericType(TypeToConvert); // Done - no conversion return null; } 

Il secondo metodo indica semplicemente se un determinato tipo è annullabile. Questo metodo è chiamato dal primo ed è utile separatamente:

  ///  /// [ public static bool IsTypeNullable(Type TypeToTest) ] ///  /// Reports whether a given Type is nullable (Nullable< Type >) ///  /// The Type to test ///  /// true = The given Type is a Nullable< Type >; false = The type is not nullable, or  /// is null. ///  ///  /// This method tests  and reports whether it is nullable (ie whether it is either a /// reference type or a form of the generic Nullable< T > type). ///  ///  public static bool IsTypeNullable(Type TypeToTest) { // Abort if no type supplied if (TypeToTest == null) return false; // If this is not a value type, it is a reference type, so it is automatically nullable // (NOTE: All forms of Nullable are value types) if (!TypeToTest.IsValueType) return true; // Report whether TypeToTest is a form of the Nullable<> type return TypeToTest.IsGenericType && TypeToTest.GetGenericTypeDefinition() == typeof(Nullable<>); } 

L’implementazione IsTypeNullable di cui sopra funziona come un campione ogni volta, ma è leggermente prolisso e lento nella sua ultima riga di codice. Il seguente corpo del codice è lo stesso di sopra per IsTypeNullable, tranne che l’ultima riga del codice è più semplice e veloce:

  // Abort if no type supplied if (TypeToTest == null) return false; // If this is not a value type, it is a reference type, so it is automatically nullable // (NOTE: All forms of Nullable are value types) if (!TypeToTest.IsValueType) return true; // Report whether an underlying Type exists (if it does, TypeToTest is a nullable Type) return Nullable.GetUnderlyingType(TypeToTest) != null; 

Godere!

marchio

PS – Informazioni su “nullability”

Dovrei ripetere una dichiarazione sul nullability che ho fatto in un post separato, che si applica direttamente per affrontare correttamente questo argomento. Cioè, credo che il focus della discussione qui non dovrebbe essere come verificare se un object è un tipo Nullable generico, ma piuttosto se si può assegnare un valore di null a un object del suo tipo. In altre parole, penso che dovremmo determinare se un tipo di object è annullabile, non se è Nullable. La differenza è nella semantica, vale a dire le ragioni pratiche per determinare il nullability, che di solito è tutto ciò che conta.

In un sistema che utilizza oggetti con tipi possibilmente sconosciuti fino al momento dell’esecuzione (servizi Web, chiamate remote, database, feed, ecc.), Un requisito comune è determinare se un object nullo può essere assegnato o se l’object potrebbe contenere un null. L’esecuzione di tali operazioni su tipi non annulli probabilmente produrrà errori, di solito eccezioni, che sono molto costosi in termini di prestazioni e requisiti di codifica. Per adottare l’approccio altamente preferito di evitare protriggersmente tali problemi, è necessario determinare se un object di un tipo arbitrario è in grado di contenere un valore nullo; cioè, se è generalmente ‘nullable’.

In un senso molto pratico e tipico, il nullability in termini .NET non implica necessariamente che il Type di un object sia una forma di Nullable. In molti casi, infatti, gli oggetti hanno tipi di riferimento, possono contenere un valore nullo e quindi sono annullabili; nessuno di questi ha un tipo Nullable. Pertanto, per scopi pratici nella maggior parte degli scenari, il test dovrebbe essere fatto per il concetto generale di nullability, rispetto al concetto di Nullable dipendente dall’implementazione. Quindi non dovremmo rimanere bloccati concentrandoci esclusivamente sul tipo .NET Nullable, ma piuttosto incorporare la nostra comprensione delle sue esigenze e del suo comportamento nel processo di concentrazione sul concetto generale e pratico di nullability.

La risposta di Lyman è ottima e mi ha aiutato, tuttavia, c’è un altro bug che deve essere risolto.

Nullable.GetUnderlyingType(type) dovrebbe essere chiamato solo se il tipo non è già un tipo Nullable . In caso contrario, sembra erroneamente restituire null quando il tipo deriva da System.RuntimeType (come quando passo in typeof(System.Int32) ). La versione qui sotto evita di dover chiamare Nullable.GetUnderlyingType(type) controllando se invece il tipo è Nullable .

Sotto troverai una versione ExtensionMethod di questo metodo che restituirà immediatamente il tipo a meno che non sia un ValueType che non è già Nullable .

 Type NullableVersion(this Type sourceType) { if(sourceType == null) { // Throw System.ArgumentNullException or return null, your preference } else if(sourceType == typeof(void)) { // Special Handling - known cases where Exceptions would be thrown return null; // There is no Nullable version of void } return !sourceType.IsValueType || (sourceType.IsGenericType && sourceType.GetGenericTypeDefinition() == typeof(Nullable<>) ) ? sourceType : typeof(Nullable<>).MakeGenericType(sourceType); } 

(Mi dispiace, ma non potevo semplicemente postare un commento alla risposta di Lyman perché ero nuovo e non avevo ancora abbastanza rep).

Non c’è nulla di costruito in ciò che io conosca, come int? , ecc. è solo zucchero sintattico per Nullable ; e non viene dato un trattamento speciale oltre a quello. È particolarmente improbabile dato che stai cercando di ottenere questo dalle informazioni sul tipo di un determinato tipo. In genere ciò richiede sempre un po ‘di “roll your own” code come dato. Dovresti usare Reflection per creare un nuovo tipo di Nullable con il parametro type del tipo di input.

Modifica: come suggeriscono i commenti, in realtà Nullable<> viene trattato in modo speciale e nel runtime per l’avvio come spiegato in questo articolo .