比较未知对象类型的值

时间:2014-11-10 23:26:05

标签: c# enums

我想做this question之类的事情,但它并没有像我期待的那样发挥作用。

我有一个对象属性及其类型的列表,一个未知对象,以及我想从对象中忽略的默认值类型列表。

public void GetOnlyNonDefault(object oObject, IgnoreValues ignoreValues)
{
    //properties is set beforehand
    for (int i = 0; i < properties.Count; i++)
    {
        object originalValue = 
            oObject
                .GetType()
                .GetProperty(properties[i].Name)
                .GetValue(oObject, null);

        //retrieving the default value I want to ignore for this property
        object ignoreValue = ignoreValues.GetDefaultOf(properties[i]);

        //Problem here

        //This doesn't work
        if (originalValue == ignoreValue) { continue; }

        //This works for nearly everything BUT enums
        if (ValueType.Equals(originalValue, ignoreValue)) { continue; }
    }
}

我从here读取枚举'默认值为零,这就是当类型为枚举时我从GetDefaultOf返回的内容。 如何通过上述代码中包含枚举的所有值类型的值进行比较?

编辑:可能相关,但我在oObject课程中使用的枚举没有任何设置为0的值,它们都从1开始。

public enum UserStatus 
{
    Regular = 1, Manager = 2, Director = 3, Admin = 4
}

编辑²这是我正在尝试的代码的基本版本,给出了我遇到的结果:http://pastebin.com/rfJA9CGp

我无法真正更改枚举,因为这是代码的重点,我不知道运行时的对象是什么,也不知道它的属性,但是我想要找出与定义的默认值不同的任何值(类{ {1}}包含所有值类型的默认值。

当它是枚举时,我无法转换为IgnoreValues,因为我忽略了在代码中实际定义了int的枚举的情况,所以我正在寻找任何方式比较值。

1 个答案:

答案 0 :(得分:4)

当运算符==被赋予静态类型为object的值时,它会进行原始参考比较。当放入变量类型object时(以及从反射调用返回时),必须将值类型装箱,因此比较将始终为false,因为即使相等的值也会被装箱到两个不同的实例。

比较枚举的一种方法是将值拆分为int:

        object foo1 = Foo.A;
        object foo2 = Foo.A;
        Console.WriteLine(foo1 == foo2);              // False
        Console.WriteLine((int) foo1 == (int) foo2);  // True

当变量没有保存可以解包为int的内容时,此代码将失败,因此需要格外小心。特别是,如果枚举的底层类型不是int(可能发生),它也会导致运行时异常。所以alernative是Enum.Equals,它支持不同底层类型的枚举:

        object foo = Foo.A;
        if (foo.GetType().IsEnum)
            Console.WriteLine(Enum.Equals(foo, your-default-value));

现在你已经展示了如何获得要比较的默认值,我知道问题是什么。您将整数 0传递给Enum.Equals。该方法以整数永远不等于枚举值的方式编写。获取默认值并不是很明显:

        object foo = Foo.A;
        object defaultEnumValue = Activator.CreateInstance(foo.GetType()))

        Enum.Equals(foo, defaultEnumValue);

你可能已经注意到这是相对神秘的。这是因为当您的代码涉及处理所有可能的类型时,C#通常不是很好。这些类型是在编译时确定的,当然,当您编写检查任意对象的代码时,这是不可能的。