开发者

C# predicate that returns whether a boxed value type is the default for that type

开发者 https://www.devze.com 2023-03-18 05:23 出处:网络
Is it possible to crea开发者_JS百科te a method that takes a boxed value type and returns whether that value type is equal to the default for that type?

Is it possible to crea开发者_JS百科te a method that takes a boxed value type and returns whether that value type is equal to the default for that type?

So I want to create a method with the following signature:

bool IsDefault(object boxedValueType);

Note: the following code will not work as T gets set to type object so default(T) will always be null.

bool IsDefault<T>(T input)
{
    return Equals(input, default(T));
}


With reflection, but it's a slow method

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("1 = " + IsDefault(1));
        Console.WriteLine("0 = " + IsDefault(default(int)));

        Console.WriteLine("1.0 = " + IsDefault(1.0));
        Console.WriteLine("0.0 = " + IsDefault(default(double)));

        Console.WriteLine("Today = " + IsDefault(DateTime.Today));
        Console.WriteLine("1.1.1 = " + IsDefault(default(DateTime)));

        //Console.WriteLine(IsDefault(""));
        //Console.WriteLine(IsDefault(default(string)));

        Console.ReadKey();
    }

    static bool IsDefault(object boxedValueType)
    {
        if (boxedValueType == null) throw new ArgumentNullException("boxedValueType");

        var t = boxedValueType.GetType();
        if (!t.IsValueType) throw new ArgumentOutOfRangeException("boxedValueType");

        object def = Activator.CreateInstance(t);
        return boxedValueType.Equals(def);
    }
}


You can use reflection to get the default value of the type. See this question about getting default values through reflection. Replace your call to default(T) with a call to that function:

return input.Equals(GetDefault(input.GetType());


Using reflection, you can invoke a generic method using the value's type:

public static bool IsDefault(object value)
{
    if (value == null)
    {
        throw new ArgumentNullException("value");
    }
    return (bool)typeof(Program).GetMethod("IsDefaultGeneric")
                                .MakeGenericMethod(value.GetType())
                                .Invoke(null, new object[] { value });
}

public static bool IsDefaultInternal<T>(T value)
    where T : struct, IEquatable<T>
{
    return value.Equals(default(T));
}


You may be better suited by using nullable types instead of boxed default values. It is easy to test for null, and nullable types are usually a cleaner design decision than special values.


Code + Unit test which will tell you whether a boxed or unboxed object is its default value. Also included generic version.

    [Test]
    public void BoxedIntIsDefault()
    {
        Assert.That(IsDefault((object)0), Is.True);
        Assert.That(IsDefault((object)1), Is.False);
        Assert.That(IsDefault<object>(0), Is.True);
        Assert.That(IsDefault<object>(1), Is.False);

    }
    bool IsDefault(object obj)
    {
        return Equals(obj, GetDefault(obj.GetType()));                
    }

    bool IsDefault<T>(T input)
    {
        return Equals(input, GetDefault(input.GetType()));
    }

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


if you want to just use the default constructor for the default value it can be

bool IsDefault<T>(T input)
{
    return EqualityComparer<T>.Default.Equals(value, Activator.CreateInstance<T>());
}
0

精彩评论

暂无评论...
验证码 换一张
取 消