2011-05-17 134 views
17

令人驚訝的是下面的代碼失敗的斷言:通過反射檢測可空類型

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

所以只是出於好奇,你怎麼能確定給定的情況下是可空<>對象或沒有?

+1

的可能重複[如何檢查對象是否爲空?](http://stackoverflow.com/questions/374651/how-檢查對象是否可爲空) – nawfal 2013-10-10 07:07:12

回答

38

那麼首先,Nullable<T>是一個結構體,所以沒有這樣的對象對象。你不能調用GetType(),因爲這會填充值(在這一點上你得到空值,因此是一個例外,或一個盒裝非空值,因此不是你想要的類型)。

(拳擊是怎麼在這裏搞亂你的斷言 - 我會假設,IsType接受object。)

您可以使用類型推斷,雖然得到變量的類型作爲類型參數:

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

當你在編譯時知道確切的類型時,這不是一個巨大的使用量,就像在你的例子中那樣,但它對泛型很有用。 (當然,還有其他的實現方法)。

你的真實生活情況如何?我認爲這不是一個這樣的斷言,因爲你在編譯時知道這個答案。

+1

非常棘手!似乎這樣做。現在我只需要記住爲什麼我想知道那個...... – 2011-05-17 06:14:02

+0

另外我從來沒有意識到結構體沒有GetType(),但是我應該明白這一點,因爲我明白它們被裝箱得到這樣的東西。 – 2011-05-17 06:15:00

+0

@ justin.m.chase: - 而是因爲調用非虛,他們不能重寫* *它,這意味着該值始終裝箱......然後螺絲事情的Structs從'object'繼承'GetType'當原始值可以爲空時啓動。 – 2011-05-17 06:17:14

0

什麼命名空間是Assert in?

下返回true如你所願:

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

雖然它值得注意的是,typeof(Nullable<int>).IsInstanceOfType(42)也返回true - 這是因爲該方法接受一個object等被盒裝的Nullable<int>

+0

斷言是xUnit的,但我只是想在一般的說,該聲明應該會成功。 – 2011-05-17 06:08:32

+0

另外,我不認爲上述作品......嗯技術上它返回true,但我相信這是一個假陽性,因爲這也將返回true:typeof運算(可空).IsInstanceOfType(0) – 2011-05-17 06:09:15

+0

@Kragen:用試試吧' int wtf = 0;'和'int? wtf = null;'一些令人驚訝的結果。拳擊使得這種方法簽名無法真正做到你想要的。編輯:在你編輯之後,仍然有一個問題 - '42'' *不會*作爲'Nullable '裝箱。相反,'0'被裝箱爲'int'裝箱類型。沒有辦法構造可空類型的盒裝值。 – 2011-05-17 06:09:22

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

這是輝煌的,它給出了聲明的類型(不像'object i = 0; i.GetType()== typeof(int);'')中的底層類型。但是如果要獲得聲明類型,爲什麼不簡單地使我們的類型推斷?就像'public Type GetDeclaredType (this T t){return typeof(T); }'。更可讀。 – nawfal 2016-07-02 07:10:15

0

這裏是我想出了,周圍的一切似乎失敗 - 至少在便攜式類庫/DOTNET的核心與> = C#6

基本上你擴展泛型類型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運行時的工作。

2

我喜歡@ jon-spectet答案,但它只適用於你知道你正在測試的類型。在我們的世界中,我們使用反射來打開對​​象,並根據正則表達式測試值。

簡化任何類型的擴展工作對我們來說都更好。

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

泛型是生命的血液,但有時... :)