检查给定对象(引用或值类型)是否等于其默认值

我正试图找到一种方法来检查并查看给定对象的值是否等于其默认值。 我环顾四周想出来:

public static bool IsNullOrDefault(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)。

我开始认为这可能是不可能的。

在您的示例中,您的整数被装箱,因此您的T将成为object ,而object的默认值为null,因此对您来说没有价值。 如果对象是值类型,则可以获取它的一个实例(这将是默认值)以用作比较。 就像是:

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

在诉诸于此之前,您需要处理其他可能性。 Marc Gravell的回答提出了一些值得考虑的好点,但对于你的方法的完整版本,你可能会有

 public static bool IsNullOrDefault(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; } 

如果o为null,则在非generics( 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 object defaultValue = Activator.CreateInstance(type); // must exist for structs return value.Equals(defaultValue); 

通过将运行时类型作为参数扩展Marc 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)返回一个对象,并且值类型被加框,所以我不能使用generics方法。 通过将propertyInfo.PropertyType作为第二个参数传递给此方法,我可以避免generics方法对盒装值类型的问题。

将Anthony Pegram的答案转换为扩展方法:

 using System; //Adapted from https://stackoverflow.com/a/6553276/1889720 public static class ObjectExtensions { public static bool IsNullOrDefault(this TObject argument) { // deal with normal scenarios if (argument == null) { return true; } if (object.Equals(argument, default(TObject))) { return true; } // deal with non-null nullables Type methodType = typeof(TObject); 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; } } 

用法语法:

 myVariable.IsNullOrDefault(); 

以下将对其进行排序。

  public static bool IsNullOrDefault(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; } 

制作扩展方法

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

linq表达式的解决方案。 对类型的第一次调用将相对较慢,但它应该像通常的代码一样快。

 public static class DefaultHelper { private delegate bool IsDefaultValueDelegate(object value); private static readonly ConcurrentDictionary Delegates = new ConcurrentDictionary(); public static bool IsDefaultValue(this object value) { var type = value.GetType(); var isDefaultDelegate = Delegates.GetOrAdd(type, CreateDelegate); return isDefaultDelegate(value); } private static IsDefaultValueDelegate CreateDelegate(Type type) { var parameter = Expression.Parameter(typeof(object)); var expression = Expression.Equal( Expression.Convert(parameter, type), Expression.Default(type)); return Expression.Lambda(expression, parameter).Compile(); } }