如何将System.Type转换为可空的版本?

这又是其中一个:“有没有一种更简单的内置方式来做事,而不是我的帮手方法?”

因此,从可空types获取底层types很容易,但是如何获得.NETtypes的可空版本?

所以我有

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

而且我要

 int? DateTime? 

要么

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

有没有内置的方法?

这是我使用的代码:

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

编辑:原始代码有一个错误,如果它本身是一个Nullable<T> ,它会performance出意外。

我已经在我的实用程序库中写入了一些我非常依赖的方法。 第一种是将任何types转换为相应的可空<Type>forms的方法:

  /// <summary> /// [ <c>public static Type GetNullableType(Type TypeToConvert)</c> ] /// <para></para> /// Convert any Type to its Nullable&lt;T&gt; form, if possible /// </summary> /// <param name="TypeToConvert">The Type to convert</param> /// <returns> /// The Nullable&lt;T&gt; 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&lt;T&gt;"/> 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; } 

第二种方法只是报告一个给定的types是否可以为空。 这个方法被第一个调用,并分别是有用的:

  /// <summary> /// [ <c>public static bool IsTypeNullable(Type TypeToTest)</c> ] /// <para></para> /// Reports whether a given Type is nullable (Nullable&lt; Type &gt;) /// </summary> /// <param name="TypeToTest">The Type to test</param> /// <returns> /// true = The given Type is a Nullable&lt; Type &gt;; 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 (ie whether it is either a /// reference type or a form of the generic Nullable&lt; T &gt; 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<>); } 

上面的IsTypeNullable实现每次都像champ一样工作,但是在最后一行代码中它稍微冗长而且速度很慢。 以下代码体与上面的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 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; 

请享用!

标记

PS – 关于“可空性”

我应该在一个单独的post中重复关于可空性的陈述,这个陈述直接适用于正确地处理这个话题。 也就是说,我相信这里讨论的焦点不应该是如何检查一个对象是否是一个通用的Nullabletypes,而是一个可以赋值为null的types的对象。 换句话说,我认为我们应该确定一个对象types是否可以为null,而不是Nullable。 不同之处在于语义,即决定可空性的实际原因,这通常是重要的。

在一个系统中使用的对象的types可能直到运行时(web服务,远程调用,数据库,提要等等)都是未知的,一个常见的要求是确定一个null是否可以被分配给该对象,或者该对象是否可能包含一个null。 对不可空的types执行这样的操作可能会产生错误,通常是例外,在性能和编码要求方面都是非常昂贵的。 为了采取主动避免这种问题的高度优选的方法,有必要确定任意types的对象是否能够包含空值; 即它是否一般是“可空的”。

在一个非常实际和典型的意义上,.NET中的可空性并不一定意味着一个对象的Type是一个可为空的forms。 事实上在很多情况下,对象具有引用types,可以包含空值,因此都是可以为空的; 这些都没有可空types。 因此,对于大多数情况下的实际应用,应该针对可空性的一般概念进行testing,而对于Nullable的实现依赖概念进行testing。 所以我们不应该把注意力集中在.NET Nullabletypes上,而是把我们对它的需求和行为的理解纳入关注可空性的一般的,实用的概念的过程中。

莱曼的回答非常好,帮助了我,但还有一个问题需要解决。

Nullable.GetUnderlyingType(type)只应该被调用,如果types不是一个Nullabletypes。 否则,当types从System.RuntimeType派生(例如,当我通过typeof(System.Int32) )时,它似乎错误地返回null。 下面的版本避免需要调用Nullable.GetUnderlyingType(type)来检查types是否为Nullable

下面你会发现这个方法的一个ExtensionMethod版本,它将立即返回该types, 除非它是一个不是NullableValueType

 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); } 

(对不起,但是我不能简单的给莱曼的回答发表评论,因为我是新的,没有足够的代表。)

我所知道的内容没有任何内容,如int? 等等只是Nullable<T>语法糖; 并没有给予特别的待遇。 特别是你试图从给定types的types信息中获得这个信息。 通常情况下,总是需要一些“滚动自己的”代码。 您将不得不使用Reflection来创build一个新的Nullabletypes的inputtypes的参数types。

编辑:由于意见build议实际上Nullable<> 专门处理,并在运行时启动,如本文所述 。