【问题标题】:I thought Object.Equals(Object, Object) support bitwise equality and not value equality我认为 Object.Equals(Object, Object) 支持按位相等而不是值相等
【发布时间】:2011-04-22 08:04:16
【问题描述】:

静态方法Object.Equals(Object, Object) 支持引用类型的引用相等,以及值类型的按位相等,在按位相等的情况下,比较的对象具有相同的二进制表示,而比较的值相等对象具有相同的值,即使它们具有不同的二进制表示。

例如,由于i1b1 是不同的类型,它们没有相同的二进制表示,因此Object.Equals(Object, Object) 返回false

        int  i1 = 100;
        byte b1 = 100;
        Console.WriteLine(Object.Equals(i1, b1));//false

Object.Equals(Object, Object) 在比较d1d2 时也应该返回false(因为这两个变量具有相同值的不同二进制表示),但它反而返回true,这表明它使用值来比较它们平等:

        decimal d1 = 1.10M;
        decimal d2 = 1.100M;
        Console.WriteLine(Object.Equals(d1, d2)); //true

在比较 d1d2 时,Object.Equals(Object, Object) 不应该返回 False 吗?

来自http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

例如,考虑两个 Decimal 代表数字的对象 1.10 和 1.1000。 Decimal 对象没有按位相等,因为 他们有不同的二进制 陈述来解释 不同数量的尾随零。

感谢

【问题讨论】:

  • 这是你发现的一个奇怪的错误

标签: c#


【解决方案1】:

Decimal 是一种值类型,Equals 方法实际上使用反射比较其所有字段。更多详情请参考MSDN:

ValueType.Equals Method

最后,您从 MSDN 获得的范围是不完整的。这里是:

例如,考虑两个 Decimal 代表数字的对象 1.10 和 1.1000。 Decimal 对象没有按位相等,因为 他们有不同的二进制 陈述来解释 不同数量的尾随零。 然而,这些物品是有价值的 平等,因为数字 1.10 和 1.1000 被认为是相等的,因为尾随 零是微不足道的。

【讨论】:

    【解决方案2】:

    Object.Equals 应该实现值(不是按位)相等。

    在Decimal的情况下,两个对象的类型相同且值相等,所以结果为真。

    在int、byte的情况下,对象的类型不同,所以结果为假。

    【讨论】:

    • »在 int、byte 情况下,对象属于不同类型,因此结果为 false。« Int32.Equals(Object obj) 如果 obj 是 Int32 的实例并且等于这个实例。如果 obj 是 byte 类型,那么它返回 False。这是否意味着 Int32.Equals(Object) 使用按位比较?否则,为什么仅仅因为 obj 的类型是 byte 而不是 int 就返回 false?
    • 如果 x 的类型不正确,几乎所有 Object.Equals(x) 的覆盖都返回 false。通常,该方法的第一条语句是“if (!(x is typeof(...)) return false;”或一些变体。
    • 知道为什么会做出相同但不同类型的值不应该被视为相等的决定吗?
    • 因为您无法将一种类型的值替换为另一种类型的值而不会出现潜在问题。该类型需要不同数量的字节存储在内存中,或者您可能会溢出/下溢新类型。
    • 这是值类型和引用类型的区别。值类型比较它们的值。对于引用类型,仅比较引用(指针)。
    【解决方案3】:

    您可以使用反射器之类的工具查看 Object.Equals(Object, Object) 的来源。

    这里是 Object.Equals(Object, Object) 的源代码:

    public static bool Equals(object objA, object objB)
    {
        return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)));
    }
    

    让我们检查一下子句:

    (objA == objB):这是对象相等运算符,它检查这两个对象是否引用同一个对象。这个子句对我们的情况是错误的。

    (objA != null) && (objB != null):我们的情况就是这样。

    objA.Equals(objB):这是真的(它委托给 Decimal.Equals(Object))

    我们在 || 运算符的 RHS 上找到了所有 true,因此整个语句的计算结果为 true。

    【讨论】:

    • Int32.Equals(Object obj) 如果 obj 是 Int32 的实例并且等于该实例的值,则返回 true。如果 obj 是 byte 类型,则返回 False。这是否意味着 Int32.Equals(Object) 使用按位比较?否则,为什么仅仅因为 obj 的类型是 byte 而不是 int 就返回 false?
    • 可能会检查类型。如果 obj 不是 Int32 的实例,则返回 false。
    • 它确实检查类型。这里是 Int32.Equals(object Obj),反编译:public override bool Equals(object obj) { if (!(obj is int)) return false; else return this == (int) obj; }
    【解决方案4】:

    来自 MSDN:

    http://msdn.microsoft.com/en-us/library/w4hkze5k.aspx

    请注意,派生类型可能会覆盖 Equals 方法以实现值相等。值相等意味着被比较的对象具有相同的值但不同的二进制表示。

    Decimal 肯定有一个 Equals 覆盖,这可以在元数据中看到。

    【讨论】:

    • 该页面用于静态 Equals 方法。
    • 静态 Equals 方法调用另一个。 (只要两个对象都存在且引用不相等)
    • 据我所知,Int32.Equals,Byte.Equals 和 Decimal.Equals(Object) 不使用值相等?!
    【解决方案5】:

    Object.Equals(Object objA, Object objB) 首先进行快速参考检查 (objA == objB)。如果失败,它会尝试调用 Decimal 覆盖的虚拟 Object.Equals(Object obj) 以提供值相等。

    【讨论】:

    • 据我所知,Int32.Equals,Byte.Equals 和 Decimal.Equals(Object) 不使用值相等?!
    【解决方案6】:

    没办法,按位相等是没有意义的,而且永远不会正确。无论以哪种按位格式存储,我们都不在乎我们关心实际的业务价值。

    出于商业或科学目的,1.10 和 1.100 相同。按位比较意味着词法比较,这是错误的。 “1.10”和“1.100”是不同的,因为它们代表不正确的词汇序列。

    如果您想比较实际位,那么您应该使用 BitConverter.GetBytes 它将为您提供实际位序列。

    Array.Compare( 
       BitConverter.GetBytes((decimal)1.10),
       BitConverter.GetBytes((decimal)1.100))
    

    我不知道是否有 Array.Compare 方法,但您可以创建一个并希望您明白这一点。

    【讨论】:

    • 你应该写 1.10m 而不是演员表。
    • 在很多情况下,Equals(Object) 的类型行为与其他 Equals 重载或 == 的行为不匹配。我建议Equals(Object) 应该代表一种比其他形式更严格的平等形式:应该是“应该将X 视为可替代Y”。我会假设由于1.0m1.00m 的行为不同,即使1.0m.Equals(1.00m) 为真,1.0m.Equals((Object)1.00m) 也应该为假,就像1.0m.Equals((Object)1) 为假但1.0m.Equals(1) 为真一样。
    猜你喜欢
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 2021-04-15
    • 2019-01-12
    • 2020-12-17
    • 2018-05-24
    • 1970-01-01
    相关资源
    最近更新 更多