簡體   English   中英

通過反射檢測可空類型

[英]Detecting a Nullable Type via reflection

令人驚訝的是,以下代碼未能通過 Assert:

int? wtf = 0;
Assert.IsType<Nullable<int>>(wtf);

因此,出於好奇,您如何確定給定實例是否為 Nullable<> object?

首先, Nullable<T>是一個結構體,所以沒有這樣的對象 您不能調用GetType() ,因為這會裝箱該值(此時您要么獲得 null 從而導致異常,要么獲得裝箱的不可為空值,因此不是您想要的類型)。

(拳擊在這里弄亂了你的斷言 - 我假設IsType接受object 。)

您可以使用類型推斷來獲取變量的類型作為類型參數:

public bool IsNullable<T>(T value)
{
    return Nullable.GetUnderlyingType(typeof(T)) != null;
}

當您在編譯時知道您的示例中的確切類型時,這並不是大量使用,但它對泛型很有用。 (當然,還有其他實現方式。)

你的現實生活是怎樣的? 我認為這不是這樣的斷言,因為您在編譯時就知道了這個斷言。

我喜歡@jon-skeet 的答案,但它只有在您知道要測試的類型時才有效。 在我們的世界中,我們使用反射來打開對​​象並針對正則表達式測試值。

簡化適用於任何類型的擴展對我們來說效果更好。

public static bool IsNullable(this Type type)
{
    return Nullable.GetUnderlyingType(type) != null;
}

仿制葯是生命的血液,但有時... :)

int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
    type.GetGenericTypeDefinition() == typeof(Nullable<>);

這是我想出的,因為其他一切似乎都失敗了 - 至少在可移植類庫/ DotNet Core with >= C# 6

基本上,您擴展泛型 Type ObjectNullable<T>並使用與基礎類型匹配的靜態擴展方法將被調用並優先於泛型T擴展方法的事實。

public static partial class ObjectExtension
{
    public static bool IsNullable<T>(this T self)
    {
        return false;
    }
}

一個用於Nullable<T>

public static partial class NullableExtension
{
    public static bool IsNullable<T>(this Nullable<T> self) where T : struct
    {
        return true;
    }
}

使用反射和type.IsGenerictype.GetGenericParameters()在我當前的 .NET 運行時集上不起作用。

Assert在什么命名空間中?

如您所料,以下返回true

int? wtf = 0;
if (typeof(Nullable<int>).IsInstanceOfType(wtf))
{
    // Do things
}

盡管值得注意的是typeof(Nullable<int>).IsInstanceOfType(42)也返回 true - 這是因為此方法接受一個object ,因此被裝箱為Nullable<int>

它對我有用,也希望對你有用。

public static bool IsNullable(this Type type)
{
    return Nullable.GetUnderlyingType(type) != null;
}

基於弗拉基米爾的回答

public static class GenericExtensions
{
   public static bool IsNullable<T>(this T item) =>
     TypedReference.GetTargetType(__makeref(item)).FullName.Contains("System.Nullable");
}

用法:

int? nullableInt = 42;
bool nIntIsNullable = nullableInt.IsNullable();

持續時間:平均機器<2ms。

評論:

這對我有用,可以檢查類型是否為 Nullable..

type.Assembly.FullName.StartsWith("System") && type.Name.Contains("Nullable");

只有這種方式適用於我使用 .net core 7 的情況

bool isNullable = propertyInfo.GetMethod is null ? false : new NullabilityInfoContext().Create(propertyInfo.GetMethod.ReturnParameter).ReadState == NullabilityState.Nullable;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM