在尝试在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.Data
和d
两者都具有值"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
确实如此.
==
运算符是否仅为值类型重载?
有两个原因:
Equals
不受限制,==
反之亦然,默认情况下检查引用相等性:
正如你可以阅读.Equals
vs==
的规格:
默认情况下,运算符
==
通过确定两个引用是否指示相同的对象来测试引用相等性,因此引用类型不需要实现运算符==
以获得此功能.当一个类型是不可变的,意味着实例中包含的数据不能被改变时,重载运算符==
来比较值的相等而不是引用相等可能是有用的,因为作为不可变对象,只要它们具有相同的值,它们就可以被认为是相同的.==
不建议在非不可变类型中覆盖运算符.重载的运算符
==
实现不应该抛出异常.任何重载运算符的类型也==
应该重载运算符!=
.
虽然编译器会抛出一个错误,如果你没有覆盖它!=
,并会警告你最好覆盖两个.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#编译时唯一的绑定就是引用相等的绑定.
这是因为测试的System.Object
实现==
引用了相等,如静态Equals(object, object)
,而实例Equals(object)
是重载的,因此它会检查实际值.
当您将值类型两次打包时,您将获得两个不同的实例,因此当前引用相等性失败.
作为静态的运算符在编译时绑定,因此没有动态调度.即使字符串已经是引用类型,因此在分配给对象类型变量时也不会加框,如果其中一个操作数的静态类型不是,则可以使用==运算符进行意外的引用比较string
.