当前位置:  开发笔记 > 编程语言 > 正文

为什么在比较用相同int值装箱的两个对象类型变量时==不起作用

如何解决《为什么在比较用相同int值装箱的两个对象类型变量时==不起作用》经验,为你挑选了2个好方法。

在尝试在C#中实现一个简单的单链表时,我注意到==在比较带有int值的两个对象类型变量但工作时不起作用.Equals.

想要检查为什么会这样.

以下代码段是通用对象类型Data属性

public class Node {
    /// 
    /// Data contained in the node
    /// 
    private object Data { get; set; };
}

下面的代码遍历单链表并搜索对象类型的值 -

/// 
/// Data to be searched in all the nodes of a singly linked list
/// Traverses through each node of a singly linked list and searches for an element
/// Node if the searched element exists else null 
public Node Search(object d)
{
    Node temp = head;

    while (temp != null)
    {
        if (temp.Data.Equals(d))
        {
            return temp;
        }

        temp = temp.Next;
    }

    return null;
}

但是,如果我更换

temp.Data.Equals(d)

与temp.Data == d

它停止工作,即使temp.Datad两者都具有值"3".任何原因==不适用于对象类型变量?

这是主要功能的片段 -

SinglyLinkedList list = new SinglyLinkedList();
list.Insert(1);
list.Insert(2);
list.Insert(3);
list.Insert(4);
list.Insert(5);

list.Print();

Node mid = list.Search(3);

我相信,因为我传递一个int值3并且Search方法需要一个对象类型,所以它会成功地将3作为对象类型装箱.但是,不确定为什么==不起作用但.Equals确实如此.

==运算符是否仅为值类型重载?



1> Willem Van O..:

有两个原因:

Equals不受限制,==反之亦然,默认情况下检查引用相等性:

正如你可以阅读.Equalsvs==的规格:

默认情况下,运算符==通过确定两个引用是否指示相同的对象来测试引用相等性,因此引用类型不需要实现运算符==以获得此功能.当一个类型是不可变的,意味着实例中包含的数据不能被改变时,重载运算符==来比较值的相等而不是引用相等可能是有用的,因为作为不可变对象,只要它们具有相同的值,它们就可以被认为是相同的.==不建议在非不可变类型中覆盖运算符.

重载的运算符==实现不应该抛出异常.任何重载运算符的类型也==应该重载运算符!=.

虽然编译器会抛出一个错误,如果你没有覆盖它!=,并会警告你最好覆盖两个.Equals.GetHashCode.

所以重写/重载.Equals,==并且!=是不同的东西.重写.Equals对超载没有影响==!=.毕竟==是一个自定义操作员.虽然这样做是不明智的,但你可以将它用于其他目的而不是平等检查.

此外,运算符在编译时解析:

以下示例使用以下csharp交互式shell程序:

$ csharp
Mono C# Shell, type "help;" for help

Enter statements below.
csharp> public class Foo {
      >  
      > public int data;
      >  
      > public static bool operator == (Foo f1, Foo f2) {
      >     return f1.data == f2.data;
      > }
      >  
      > public static bool operator != (Foo f1, Foo f2) {
      >  
      >     return f1.data != f2.data;
      > }
      >  
      > }
(1,15): warning CS0660: `Foo' defines operator == or operator != but does not override Object.Equals(object o)
(1,15): warning CS0661: `Foo' defines operator == or operator != but does not override Object.GetHashCode()
csharp> object f = new Foo();
csharp> object f2 = new Foo();
csharp> f == f2
false
csharp> Foo f3 = f as Foo;
csharp> Foo f4 = f2 as Foo;
csharp> f3 == f4
true

如您所见,==如果您将对象称为object或作为,则会给出不同的结果Foo.由于你使用了一个object,C#编译时唯一的绑定就是引用相等的绑定.



2> phoog..:

这是因为测试的System.Object实现==引用了相等,如静态Equals(object, object),而实例Equals(object)是重载的,因此它会检查实际值.

当您将值类型两次打包时,您将获得两个不同的实例,因此当前引用相等性失败.

作为静态的运算符在编译时绑定,因此没有动态调度.即使字符串已经是引用类型,因此在分配给对象类型变量时也不会加框,如果其中一个操作数的静态类型不是,则可以使用==运算符进行意外的引用比较string.

推荐阅读
落单鸟人
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有