Check to see if a given object (reference or value type) is equal to its default

Viewed 19647

I'm trying to find a way to check and see if the value of a given object is equal to its default value. I've looked around and come up with this:

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

The problem I'm having is that I want to call it like this:

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

Yes o is an object, but I want to make it figure out the base type and check the default value of that. The base type, in this case, is an integer and I want to know in this case if the value is equal to default(int), not default(object).

I'm starting to think this might not be possible.

7 Answers

Converted Anthony Pegram's Answer into an extension method:

using System;

//Adapted from https://stackoverflow.com/a/6553276/1889720
public static class ObjectExtensions
{
    public static bool IsNullOrDefault<TObject>(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;
    }
}

Usage syntax:

myVariable.IsNullOrDefault();

Solution with linq expressions. First call for type will be relatively slow, but then it should work just as quick as usual code.

public static class DefaultHelper
{
    private delegate bool IsDefaultValueDelegate(object value);

    private static readonly ConcurrentDictionary<Type, IsDefaultValueDelegate> Delegates
        = new ConcurrentDictionary<Type, IsDefaultValueDelegate>();

    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<IsDefaultValueDelegate>(expression, parameter).Compile();
    }
}
Related