我在实用程序库中编写了几个方法,我非常依赖这些方法。第一个是将任何 Type 转换为其对应的 Nullable 形式的方法:
/// <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;
}
第二种方法只是报告给定类型是否可以为空。该方法由第一个调用,单独有用:
/// <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<>);
}
上面的 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 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;
享受吧!
标记
附: - 关于“可空性”
我应该重复我在另一篇文章中关于可空性的声明,该声明直接适用于正确解决该主题。也就是说,我认为这里讨论的重点不应该是如何检查一个对象是否是一个泛型的 Nullable 类型,而是是否可以将 null 值赋给该类型的对象。换句话说,我认为我们应该确定一个对象类型是否可以为空,而不是它是否可以为空。区别在于语义,即确定可空性的实际原因,这通常是最重要的。
在使用对象的类型在运行时可能未知的系统中(Web 服务、远程调用、数据库、提要等),一个常见的要求是确定是否可以将空值分配给对象,或者是否对象可能包含一个空值。对不可为空的类型执行此类操作可能会产生错误,通常是异常,这在性能和编码要求方面都非常昂贵。为了采取主动避免此类问题的首选方法,有必要确定任意类型的对象是否能够包含空值;即,它是否通常是“可空的”。
在非常实际和典型的意义上,.NET 术语中的可空性并不一定意味着对象的类型是可空的形式。事实上,在很多情况下,对象都有引用类型,可以包含空值,因此都是可以为空的;这些都没有 Nullable 类型。因此,在大多数情况下,出于实际目的,应针对可空性的一般概念进行测试,而不是可空性的依赖于实现的概念。因此,我们不应仅仅关注 .NET Nullable 类型,而是将我们对其要求和行为的理解融入到可空性的一般实用概念的过程中。