Проверьте, соответствует ли данный объект (ссылка или тип значения) его умолчанию
Я пытаюсь найти способ проверить и посмотреть, соответствует ли значение данного объекта его значению по умолчанию. Я оглянулся и придумал следующее:
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 - объект, но я хочу, чтобы он вычислил базовый тип и проверил значение по умолчанию. Базовый тип в этом случае является целым числом, и я хочу знать в этом случае, если значение равно по умолчанию (int), а не по умолчанию (объект).
Я начинаю думать, что это может быть невозможно.
Ответы
Ответ 1
В вашем примере ваше целое число помещено в квадрат, и поэтому ваш T
будет object
, а значение по умолчанию объекта равно null, поэтому оно не будет ценным для вас. Если объект является типом значения, вы можете получить экземпляр его (который будет использоваться по умолчанию) для использования в качестве сравнения. Что-то вроде:
if (argument is ValueType)
{
object obj = Activator.CreateInstance(argument.GetType());
return obj.Equals(argument);
}
Вы должны иметь дело с другими возможностями, прежде чем прибегать к этому. Ответ Марка Гравелла содержит некоторые полезные моменты, но для полной версии вашего метода у вас может быть
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;
}
Ответ 2
если o
равно null, в не-generic (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);
Ответ 3
Развернувшись на 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);
}
Для тех из вас, кто будет оспаривать мой вариант использования, я хочу перечислить значения свойств на произвольном объекте, опустив свойства, установленные по умолчанию (для более кратких отображений).
Поскольку свойствоInfo.GetValue(targetObject, null) возвращает объект, а типы значений вставляются в ящик, я не могу использовать общий метод. Передавая свойствоInfo.PropertyType в качестве второго параметра этого метода, я могу избежать проблемы, которую имеет общий метод с типами полей в коробке.
Ответ 4
Далее будут отсортированы.
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;
}
Ответ 5
Сделайте способ расширения
public static class DateExtension
{
public static bool IsNullOrDefault(this DateTime? value)
{
return default(DateTime) == value || default(DateTime?) == value;
}
}