返回一个盒装值类型是否为该类型的默认值的c#谓词

本文关键字:类型 是否 默认值 谓词 盒装 一个 返回 | 更新日期: 2023-09-27 18:01:33

是否有可能创建一个方法,该方法接受盒装值类型并返回该值类型是否等于该类型的默认值?

所以我想创建一个签名如下的方法:
bool IsDefault(object boxedValueType);

注意:当T被设置为类型object时,以下代码将不起作用,因此default(T)将始终是null

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

返回一个盒装值类型是否为该类型的默认值的c#谓词

使用反射,但这是一个缓慢的方法

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

您可以使用反射来获取该类型的默认值。请参阅关于通过反射获取默认值的问题。将对default(T)的调用替换为对该函数的调用:

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

使用反射,您可以使用值的类型调用泛型方法:

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

您可能更适合使用可空类型而不是盒装默认值。对null进行测试很容易,可空类型通常是比特殊值更干净的设计决策。

代码+单元测试,它将告诉您盒装或未盒装对象是否是其默认值。还包括通用版本。

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

如果您只想使用默认构造函数作为默认值,则可以使用

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