C# 如何将 System.Type 转换为其可为空的版本?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/108104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I convert a System.Type to its nullable version?
提问by Alex Duggleby
Once again one of those: "Is there an easier built-in way of doing things instead of my helper method?"
再次是其中之一:“有没有一种更简单的内置方式来代替我的辅助方法?”
So it's easy to get the underlying type from a nullable type, but how do I get the nullable version of a .NET type?
所以从可空类型获取底层类型很容易,但是如何获取 .NET 类型的可空版本呢?
So I have
所以我有
typeof(int)
typeof(DateTime)
System.Type t = something;
and I want
而且我要
int?
DateTime?
or
或者
Nullable<int> (which is the same)
if (t is primitive) then Nullable<T> else just T
Is there a built-in method?
有内置方法吗?
采纳答案by Alex Lyman
Here is the code I use:
这是我使用的代码:
Type GetNullableType(Type type) {
// Use Nullable.GetUnderlyingType() to remove the Nullable<T> wrapper 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;
}
回答by ljs
There isn't anything built in that I know of, as the int?
, etc. is just syntactic sugar for Nullable<T>
; and isn't given special treatment beyond that. It's especially unlikely given you're attempting to obtain this from the type information of a given type. Typically that always necessitates some 'roll your own' code as a given. You would have to use Reflection to create a new Nullable
type with type parameter of the input type.
我所知道的没有内置任何内容,因为int?
等只是Nullable<T>
; 的语法糖;并且除此之外没有给予特殊待遇。考虑到您试图从给定类型的类型信息中获取此信息,这种情况尤其不可能。通常,这总是需要一些“滚动您自己的”代码作为给定。您必须使用反射来创建具有Nullable
输入类型的类型参数的新类型。
Edit:As the comments suggest actually Nullable<>
istreated specially, and in the runtime to boot as explained in this article.
编辑:正如评论所暗示的,实际上Nullable<>
被特殊对待,并在运行时启动,如本文所述。
回答by Thracx
Lyman's answer is great and has helped me, however, there's one more bug which needs to be fixed.
Lyman 的回答很好,对我有帮助,但是,还有一个错误需要修复。
Nullable.GetUnderlyingType(type)
should only be called iff the type isn't already a Nullable
type. Otherwise, it seems to erroneously return null when the type derives from System.RuntimeType
(such as when I pass in typeof(System.Int32)
). The below version avoids needing to call Nullable.GetUnderlyingType(type)
by checking if the type is Nullable
instead.
Nullable.GetUnderlyingType(type)
仅当类型不是类型时才应调用Nullable
。否则,当类型派生自时System.RuntimeType
(例如当我传入时typeof(System.Int32)
),它似乎会错误地返回 null 。下面的版本Nullable.GetUnderlyingType(type)
通过检查类型Nullable
来避免需要调用。
Below you'll find an ExtensionMethod
version of this method which will immediately return the type unlessit's a ValueType
that's not already Nullable
.
您将在下面找到ExtensionMethod
此方法的一个版本,该版本将立即返回类型,除非它是 a ValueType
that's not already 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);
}
(I'm sorry, but I couldn't simply post a comment to Lyman's answer because I was new and didn't have enough rep yet.)
(对不起,我不能简单地对 Lyman 的回答发表评论,因为我是新人,还没有足够的代表。)
回答by Mark Jones
I have a couple of methods I've written in my utility library that I've heavily relied on. The first is a method that converts any Type to its corresponding Nullable<Type> form:
我在我非常依赖的实用程序库中编写了几种方法。第一个是将任何类型转换为其对应的 Nullable<Type> 形式的方法:
/// <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;
}
The second method simply reports whether a given Type is nullable. This method is called by the first and is useful separately:
第二种方法只是报告给定的类型是否可以为空。此方法由第一个调用,单独使用:
/// <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<>);
}
The above IsTypeNullable implementation works like a champ every time, but it's slightly verbose and slow in its last code line. The following code body is the same as above for IsTypeNullable, except the last code line is simpler and faster:
上面的 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;
Enjoy!
享受!
Mark
标记
P.S. - About "nullability"
PS - 关于“可空性”
I should repeat a statement about nullability I made in a separate post, which applies directly to properly addressing this topic. That is, I believe the focus of the discussion here should not be how to check to see if an object is a generic Nullable type, but rather whether one can assign a value of null to an object of its type. In other words, I think we should be determining whether an object type is nullable, not whether it is Nullable. The difference is in semantics, namely the practical reasons for determining nullability, which is usually all that matters.
我应该重复我在另一篇文章中所做的关于可空性的声明,它直接适用于正确解决这个主题。也就是说,我认为这里讨论的重点不应该是如何检查一个对象是否是通用的 Nullable 类型,而是是否可以为它的类型的对象分配一个 null 值。换句话说,我认为我们应该确定一个对象类型是否可以为 null,而不是它是否为 Nullable。区别在于语义,即确定可空性的实际原因,这通常是最重要的。
In a system using objects with types possibly unknown until run-time (web services, remote calls, databases, feeds, etc.), a common requirement is to determine whether a null can be assigned to the object, or whether the object might contain a null. Performing such operations on non-nullable types will likely produce errors, usually exceptions, which are very expensive both in terms of performance and coding requirements. To take the highly-preferred approach of proactively avoiding such problems, it is necessary to determine whether an object of an arbitrary Type is capable of containing a null; i.e., whether it is generally 'nullable'.
在使用类型可能在运行时之前未知的对象(Web 服务、远程调用、数据库、提要等)的系统中,一个常见的要求是确定是否可以将空值分配给对象,或者对象是否可能包含一个空值。对不可空类型执行此类操作可能会产生错误,通常是异常,这在性能和编码要求方面都非常昂贵。为了采取主动避免此类问题的首选方法,需要确定任意类型的对象是否能够包含空值;即,它是否通常是“可空的”。
In a very practical and typical sense, nullability in .NET terms does not at all necessarily imply that an object's Type is a form of Nullable. In many cases in fact, objects have reference types, can contain a null value, and thus are all nullable; none of these have a Nullable type. Therefore, for practical purposes in most scenarios, testing should be done for the general concept of nullability, vs. the implementation-dependent concept of Nullable. So we should not be hung up by focusing solely on the .NET Nullable type but rather incorporate our understanding of its requirements and behavior in the process of focusing on the general, practical concept of nullability.
在非常实际和典型的意义上,.NET 术语中的可空性并不一定意味着对象的类型是 Nullable 的一种形式。实际上很多情况下,对象都有引用类型,可以包含空值,因此都是可以为空的;这些都没有 Nullable 类型。因此,在大多数情况下,出于实际目的,应该针对可空性的一般概念进行测试,而不是 Nullable 的实现相关概念。因此,我们不应该仅仅关注 .NET Nullable 类型,而应该在关注可空性的一般实用概念的过程中结合我们对其要求和行为的理解。