其中一个:"是否有一种更简单的内置处理方式而不是我的帮助方法?"
所以从可空类型中获取底层类型很容易,但是如何获得.NET类型的可空版本呢?
所以我有
typeof(int) typeof(DateTime) System.Type t = something;
而且我要
int? DateTime?
要么
Nullable(which is the same) if (t is primitive) then Nullable else just T
有内置方法吗?
这是我使用的代码:
Type GetNullableType(Type type) { // Use Nullable.GetUnderlyingType() to remove the Nullablewrapper if type is already nullable. type = Nullable.GetUnderlyingType(type) ?? type; // avoid type becoming null if (type.IsValueType) return typeof(Nullable<>).MakeGenericType(type); else return type; }
我在我的实用程序库中编写了一些我非常依赖的方法.第一个是将任何Type转换为其对应的Nullable
////// [ /// The Type to convert ///public static Type GetNullableType(Type TypeToConvert) ] ////// Convert any Type to its Nullable<T> form, if possible /// /// 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; }
第二种方法只是报告给定的Type是否可为空.此方法由第一个调用,并且单独使用:
////// [ /// The Type to test ///public static bool IsTypeNullable(Type TypeToTest) ] ////// Reports whether a given Type is nullable (Nullable< Type >) /// /// 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 (i.e. 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<>); }
上面的IsTypeNullable实现每次都像一个冠军,但它的最后一个代码行略显冗长和缓慢.以下代码体与IsTypeNullable的上述代码体相同,但最后一个代码行更简单,更快:
// 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 Nullableare 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;
请享用!
标记
PS - 关于"可空性"
我应该在一个单独的帖子中重复关于可空性的声明,该声明直接适用于正确解决这个问题.也就是说,我认为这里讨论的重点不应该是如何检查一个对象是否是一个通用的Nullable类型,而是一个人是否可以为其类型的对象赋值null.换句话说,我认为我们应该确定一个对象类型是否可以为空,而不是它是否为Nullable.区别在于语义,即确定可空性的实际原因,这通常都很重要.
在使用类型可能未知的对象直到运行时(Web服务,远程调用,数据库,提要等)的系统中,常见的要求是确定是否可以为对象分配null,或者对象是否可能包含一个null.在非可空类型上执行此类操作可能会产生错误,通常是异常,这在性能和编码要求方面都非常昂贵.为了采取主动避免此类问题的高度优选方法,有必要确定任意类型的对象是否能够包含空值; 即,它是否通常是"可空的".
在一个非常实际和典型的意义上,.NET术语中的可空性并不一定意味着对象的Type是Nullable的一种形式.事实上,在很多情况下,对象具有引用类型,可以包含空值,因此都可以为空; 这些都没有Nullable类型.因此,出于实际目的,在大多数情况下,应该针对可空性的一般概念进行测试,而不是Nullable的依赖于实现的概念.所以我们不应该只关注.NET Nullable类型,而应该在关注可空性的一般实用概念的过程中结合我们对其要求和行为的理解.
莱曼的答案很棒并且帮助了我,但是还有一个需要修复的bug.
Nullable.GetUnderlyingType(type)
如果类型不是类型,则只应调用Nullable
.否则,当类型派生时System.RuntimeType
(例如当我传入时typeof(System.Int32)
),它似乎错误地返回null .以下版本Nullable.GetUnderlyingType(type)
通过检查类型是否Nullable
代替来避免需要调用.
您将在下面找到ExtensionMethod
此方法的一个版本,它将立即返回该类型,除非它还ValueType
没有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); }
(对不起,我不能简单地发表对Lyman答案的评论,因为我是新人,但还没有足够的代表.)