Проверьте, соответствует ли данный объект (ссылка или тип значения) его умолчанию

Я пытаюсь найти способ проверить и посмотреть, соответствует ли значение данного объекта его значению по умолчанию. Я оглянулся и придумал следующее:

    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;
    }
}