如何检查 .NET 中的装箱值是否为空

How to check if boxed value is empty in .NET

例如,

我有 object 类型的输入参数。而且我知道这个参数可以存储值类型 int, float, double(boxed value) 等之一。但我不知道哪种值类型会出现在这个方法中。我想检查盒装值类型是否为空。

为这段代码点赞:

bool IsEmpty(object boxedProperty)
{
    return boxedProperty == default(typeof(boxedProperty))
}

我明白了,我能做到:

bool IsEmpty(object boxedProperty)
{
    return boxedProperty is int && boxedProperty == default(int)
    || boxedProperty is float ....
}

但它看起来像是肮脏的解决方案。这个怎么做比较好?

在我看来,通用函数是一个不错的选择。 相似的东西:

    static void Main(string[] args)
    {
        object obj1 = null;
        object obj2 = "Assigned value";

        Console.WriteLine(string.Format("IsEmpty(obj1) --> {0}", IsEmpty(obj1)));
        Console.WriteLine(string.Format("IsEmpty(obj2) --> {0}", IsEmpty(obj2)));

        Console.ReadLine();
    }

    private static bool IsEmpty<T>(T boxedProperty)
    {
        T defaultProperty = default(T);
        return ReferenceEquals(boxedProperty, defaultProperty);
    }

输出:

IsEmpty(obj1) --> True
IsEmpty(obj1) --> False

我猜这样的东西可以给你一个结果供参考+盒装值类型。

public bool IsDefaultValue(object o)
{
    if (o == null)
        return true;

    var type = o.GetType();
    return type.IsValueType && o.Equals(Activator.CreateInstance(type));
}

object i = default(int);
object j = default(float);
object k = default(double);
object s = default(string);

object i2 = (int)2;
object s2 = (string)"asas";


var bi = IsDefaultValue(i); // true
var bj = IsDefaultValue(j); // true
var bk = IsDefaultValue(k); // true
var bs = IsDefaultValue(s); // true

var bi2 = IsDefaultValue(i2); // false
var bs2 = IsDefaultValue(s2); // false

如果你确定你有一个值类型,那么使用这个方法:

public bool IsDefaultBoxedValueType(object o)
{
    return o.Equals(Activator.CreateInstance(o.GetType()));
}

正如其他人指出的那样,唯一真正的方法是创建该类型的实例,然后进行比较。 (另见 how to get the default value of a type if the type is only known as System.Type? and Default value of a type at Runtime

您可以缓存结果,因此您只需创建一个默认实例 1x 类型。如果您必须多次调用检查,这可以提高效率。我使用了静态方法和字典(它不是线程安全的),但如果你愿意,你可以将它更改为实例级别。

static IDictionary<Type, object> DefaultValues = new Dictionary<Type, object>();
static bool IsBoxedDefault(object boxedProperty)
{
    if (boxedProperty == null)
        return true;
    Type objectType = boxedProperty.GetType();

    if (!objectType.IsValueType)
    {
        // throw exception or something else?? Up to how you want this to behave
        return false;
    }

    object defaultValue = null;
    if (!DefaultValues.TryGetValue(objectType, out defaultValue))
    {
        defaultValue = Activator.CreateInstance(objectType);
        DefaultValues[objectType] = defaultValue;
    }
    return defaultValue.Equals(boxedProperty);
}

测试代码

static void Test()
{
    Console.WriteLine(IsBoxedDefault(0)); // true
    Console.WriteLine(IsBoxedDefault("")); // false (reference type)
    Console.WriteLine(IsBoxedDefault(1));// false
    Console.WriteLine(IsBoxedDefault(DateTime.Now)); // false
    Console.WriteLine(IsBoxedDefault(new DateTime())); // true
}