2011-07-01 43 views
14

我試圖找到一種方法來檢查給定對象的值是否等於其默認值。我環顧四周,並提出了這一點:檢查給定對象(引用或值類型)是否等於其默認值

public static bool IsNullOrDefault<T>(T argument) 
    { 
     if (argument is ValueType || argument != null) 
     { 
      return object.Equals(argument, default(T)); 
     } 
     return true; 
    } 

我遇到的問題是,我想這樣稱呼它:

  object o = 0; 
      bool b = Utility.Utility.IsNullOrDefault(o); 

是o是一個對象,但我想使其找出基本類型並檢查其默認值。在這種情況下,基類型是一個整數,在這種情況下,我想知道該值是否等於default(int),而不是default(object)。

我開始認爲這可能是不可能的。

+0

爲什麼不把它象變種O = 0; ? – Jethro

+0

我不能這樣做,因爲我從'PropertyInfo'中的'GetValue'方法獲得了值,它只返回一個'object'。 – Brian

+0

[最有效的方法來檢查一個對象是一個值類型]的可能重複(http://stackoverflow.com/questions/5748661/most-efficient-way-to-check-if-an-object-is-a -value-type) – nawfal

回答

24

在你的例子中,你的整數是裝盒的,因此你的T將是object,對象的默認值爲null,所以這對你沒有價值。如果對象是一個值類型,您可以獲取它的一個實例(這將是默認值)用作比較。例如:

if (argument is ValueType) 
{ 
    object obj = Activator.CreateInstance(argument.GetType()); 
    return obj.Equals(argument); 
} 

在訴諸此之前,您會想要處理其他可能性。 Marc Gravell's answer帶來了一些好點的考慮,但對你的方法的完整版本,你可能有

public static bool IsNullOrDefault<T>(T argument) 
{ 
    // deal with normal scenarios 
    if (argument == null) return true; 
    if (object.Equals(argument, default(T))) return true; 

    // deal with non-null nullables 
    Type methodType = typeof(T); 
    if (Nullable.GetUnderlyingType(methodType) != null) return false; 

    // deal with boxed value types 
    Type argumentType = argument.GetType(); 
    if (argumentType.IsValueType && argumentType != methodType) 
    { 
     object obj = Activator.CreateInstance(argument.GetType()); 
     return obj.Equals(argument); 
    } 

    return false; 
} 
+0

很好的解決問題的方法。 – Keith

+1

另一種可以實現的方法是將其編碼爲擴展名: '公共靜態布爾IsNullOrDeafult (這個T參數)' – scottmgerstl

+0

正如Marc Gravell指出的那樣,但我沒有得到第一個:當一個可爲null的值被裝箱它是一個null或一個值,類型。例如。 \t object o =(int?)0; (o.GetType()== typeof(int)); //不是int? 所以,我認爲這是誤導提供了一個通用的方法,其中: \t IsNullOrDefault - 返回false,但 \t IsNullOrDefault((對象)(INT)0) - 返回true((INT)0?) (這些演員陣容並不是真正的用例,但在有用的場景中確實發生了拳擊。) IMO更好的解決方案是傳遞顯式運行時類型。 –

4

如果o爲空,在非通用(object)方法,你將不得不在沒有接入原來的類型 - 你不能做太多的事情。

因此,唯一重要的時間是不可爲空值類型,所以:

Type type = value.GetType(); 
if(!type.IsValueType) return false; // can't be, as would be null 
if(Nullable.GetUnderlyingType(type) != null) return false; // ditto, Nullable<T> 
object defaultValue = Activator.CreateInstance(type); // must exist for structs 
return value.Equals(defaultValue); 
0

下面將整理出來。

public static bool IsNullOrDefault<T>(T argument) 
{ 
    if (argument is ValueType || argument != null) 
    { 
     return object.Equals(argument, GetDefault(argument.GetType())); 
    } 
    return true; 
} 


public static object GetDefault(Type type) 
{ 
    if(type.IsValueType) 
    { 
     return Activator.CreateInstance(type); 
    } 
    return null; 
} 
1

對馬克Gravell的答案擴大,通過獲取運行時類型作爲參數:

// Handles boxed value types 
public static bool IsNullOrDefault([CanBeNull] this object @object, 
    [NotNull] Type runtimeType) 
{ 
    if (@object == null) return true; 

    if (runtimeType == null) throw new ArgumentNullException("runtimeType"); 

    // Handle non-null reference types. 
    if (!runtimeType.IsValueType) return false; 

    // Nullable, but not null 
    if (Nullable.GetUnderlyingType(runtimeType) != null) return false; 

    // Use CreateInstance as the most reliable way to get default value for a value type 
    object defaultValue = Activator.CreateInstance(runtimeType); 

    return defaultValue.Equals(@object); 
} 

對於那些你會質疑我的使用情況下,我想列出屬性的值在任意對象上,省略設置爲其默認值的屬性(用於更簡潔的顯示)。

因爲propertyInfo.GetValue(targetObject,null)返回一個對象,並且值類型被裝箱,所以我不能使用泛型方法。通過將propertyInfo.PropertyType作爲第二個參數傳遞給此方法,我可以避免泛型方法使用裝箱值類型的問題。

0

使擴展方法

public static class DateExtension 
{ 
    public static bool IsNullOrDefault(this DateTime? value) 
    { 
     return default(DateTime) == value || default(DateTime?) == value; 
    } 
}