Noch einmal eine davon: "Gibt es eine einfachere Möglichkeit, Dinge anstelle meiner Hilfsmethode zu erledigen?"
Es ist also einfach, den zugrunde liegenden Typ von einem nullbaren Typ abzurufen, aber wie erhalte ich die nullfähige Version eines .NET-Typs?
Also habe ich
typeof(int)
typeof(DateTime)
System.Type t = something;
und ich will
int?
DateTime?
oder
Nullable<int> (which is the same)
if (t is primitive) then Nullable<T> else just T
Gibt es eine eingebaute Methode?
null
Werttyps an diese Funktion tritt ein Fehler auf.type
nicht null ist, bevor Sie auf dieIsValueType
Eigenschaft zugreifen , wie @AmitG sagte. -1 bis das behoben istIch habe einige Methoden in meiner Utility-Bibliothek geschrieben, auf die ich mich stark verlassen habe. Die erste Methode konvertiert einen beliebigen Typ in die entsprechende Nullable <Type> -Form:
/// <summary> /// [ <c>public static Type GetNullableType(Type TypeToConvert)</c> ] /// <para></para> /// Convert any Type to its Nullable<T> form, if possible /// </summary> /// <param name="TypeToConvert">The Type to convert</param> /// <returns> /// The Nullable<T> converted from the original type, the original type if it was already nullable, or null /// if either <paramref name="TypeToConvert"/> could not be converted or if it was null. /// </returns> /// <remarks> /// To qualify to be converted to a nullable form, <paramref name="TypeToConvert"/> must contain a non-nullable value /// type other than System.Void. Otherwise, this method will return a null. /// </remarks> /// <seealso cref="Nullable<T>"/> 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<Type> if (TypeToConvert.IsValueType && TypeToConvert != typeof(void)) return typeof(Nullable<>).MakeGenericType(TypeToConvert); // Done - no conversion return null; }
Die zweite Methode gibt einfach an, ob ein bestimmter Typ nullwertfähig ist. Diese Methode wird von der ersten aufgerufen und ist separat nützlich:
/// <summary> /// [ <c>public static bool IsTypeNullable(Type TypeToTest)</c> ] /// <para></para> /// Reports whether a given Type is nullable (Nullable< Type >) /// </summary> /// <param name="TypeToTest">The Type to test</param> /// <returns> /// true = The given Type is a Nullable< Type >; false = The type is not nullable, or <paramref name="TypeToTest"/> /// is null. /// </returns> /// <remarks> /// This method tests <paramref name="TypeToTest"/> and reports whether it is nullable (i.e. whether it is either a /// reference type or a form of the generic Nullable< T > type). /// </remarks> /// <seealso cref="GetNullableType"/> 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<T> 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<>); }
Die obige IsTypeNullable-Implementierung funktioniert jedes Mal wie ein Champion, ist jedoch in der letzten Codezeile etwas ausführlich und langsam. Der folgende Codekörper ist der gleiche wie oben für IsTypeNullable, außer dass die letzte Codezeile einfacher und schneller ist:
// 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<T> 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;
Genießen!
Kennzeichen
PS - Über "Nullability"
Ich sollte eine Aussage über die Nichtigkeit, die ich in einem separaten Beitrag gemacht habe, wiederholen, die direkt für die richtige Behandlung dieses Themas gilt. Das heißt, ich glaube, der Fokus der Diskussion hier sollte nicht darauf liegen, zu überprüfen, ob ein Objekt ein generischer Nullable-Typ ist, sondern ob man einem Objekt seines Typs den Wert Null zuweisen kann. Mit anderen Worten, ich denke, wir sollten bestimmen, ob ein Objekttyp nullbar ist, nicht ob er nullbar ist. Der Unterschied liegt in der Semantik, nämlich den praktischen Gründen für die Bestimmung der Nullfähigkeit, was normalerweise alles ist, was zählt.
In einem System, das Objekte mit möglicherweise bis zur Laufzeit unbekannten Typen verwendet (Webdienste, Fernaufrufe, Datenbanken, Feeds usw.), besteht eine häufige Anforderung darin, zu bestimmen, ob dem Objekt eine Null zugewiesen werden kann oder ob das Objekt möglicherweise enthält eine Null. Das Ausführen solcher Operationen mit nicht nullbaren Typen führt wahrscheinlich zu Fehlern, normalerweise Ausnahmen, die sowohl hinsichtlich der Leistung als auch der Codierungsanforderungen sehr teuer sind. Um den äußerst bevorzugten Ansatz zu verfolgen, solche Probleme proaktiv zu vermeiden, muss bestimmt werden, ob ein Objekt eines beliebigen Typs eine Null enthalten kann; dh, ob es im Allgemeinen "nullbar" ist.
In einem sehr praktischen und typischen Sinne bedeutet die Nullbarkeit in .NET-Begriffen keineswegs unbedingt, dass der Typ eines Objekts eine Form von Nullable ist. In vielen Fällen haben Objekte tatsächlich Referenztypen, können einen Nullwert enthalten und sind daher alle nullwertfähig. Keiner von diesen hat einen Nullable-Typ. Aus praktischen Gründen sollten daher in den meisten Szenarien Tests für das allgemeine Konzept der Nullbarkeit im Vergleich zum implementierungsabhängigen Konzept der Nullbarkeit durchgeführt werden. Wir sollten uns also nicht nur auf den .NET Nullable-Typ konzentrieren, sondern unser Verständnis seiner Anforderungen und seines Verhaltens in den Prozess der Fokussierung auf das allgemeine, praktische Konzept der Nullbarkeit einbeziehen.
quelle
Lymans Antwort ist großartig und hat mir geholfen, aber es gibt noch einen Fehler, der behoben werden muss.
Nullable.GetUnderlyingType(type)
sollte nur aufgerufen werden, wenn der Typ noch keinNullable
Typ ist. Andernfalls scheint es fälschlicherweise null zurückzugeben, wenn der Typ abgeleitet istSystem.RuntimeType
(z. B. wenn ich übergebetypeof(System.Int32)
). Die folgende Version vermeidet das Aufrufen,Nullable.GetUnderlyingType(type)
indem überprüft wird, ob der TypNullable
stattdessen ist.Unten finden Sie eine
ExtensionMethod
Version dieser Methode, die den Typ sofort zurückgibt, sofern diesValueType
nicht bereits geschehen istNullable
.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); }
(Es tut mir leid, aber ich konnte nicht einfach einen Kommentar zu Lymans Antwort schreiben, weil ich neu war und noch nicht genug Repräsentanten hatte.)
quelle
Es ist nichts eingebaut, von dem ich weiß, da das
int?
usw. nur syntaktischer Zucker istNullable<T>
; und wird darüber hinaus nicht besonders behandelt. Es ist besonders unwahrscheinlich, dass Sie versuchen, dies aus den Typinformationen eines bestimmten Typs zu erhalten. In der Regel erfordert dies immer einen bestimmten Code. Sie müssten Reflection verwenden, um einen neuenNullable
Typ mit dem Typparameter des Eingabetyps zu erstellen .Edit: Da die Kommentare tatsächlich empfehlen
Nullable<>
sind speziell behandelt, und in der Runtime - Boot , wie unter diesem Artikel .quelle
int?
über den+
Operator hinzufügen können , wissen wir , dassNullable
s eine Sonderbehandlung erhalten, da diese Art der generischen Überladung des Operators sonst nicht funktionieren würde.