在 Java 中,以下代码可能返回 false:
IntegerPlus o1 = new IntegerPlus(1000);
IntegerPlus o2 = o1;
boolean b1 = o1 == o2;
boolean b2 = o1.Equals (o2);
这在C#中也是一个问题吗?或者 C# 执行 == 的方式是否始终为 true,即使对象被移动? (我在这里更详细地描述了 Java 问题。)
不。
在 C#/.Net 中,哈希码不参与
==
、!=
或 Equals
的默认实现。如果对象是引用类型并且由 GC 移动,则该对象之外没有任何内容会影响默认比较。
编辑:下面与比较无关的细节。
==
和 Equals
彼此没有关系(除非按照惯例)。
在 C# 中,您有 operator == 类/结构可以重载。默认行为是比较引用类型的引用,比较系统值类型的值,对于自定义“结构”,没有自动生成的
==
运算符。请注意,另一个比较 Equals
不涉及 operator ==
的默认定义。
对于预定义值类型,相等运算符 (==) 如果其操作数的值相等则返回 true,否则返回 false。对于字符串以外的引用类型,如果两个操作数引用同一个对象,则 == 返回 true。
您还可以为课程提供您的自定义
Object.Equals
。对于重新定义 ==
或 Equals
的类,良好的做法是重新定义所有与比较相关的方法,使其一致地工作(==
、!=
、Equals(object other)
和 GetHashCode
;可能是 Equals(myType other)
)。
.Net 中
GetHashCode
的唯一用途是基于哈希的集合,例如 Dictionary
、HashSet
。检查 C# 中的 GetHashCode 指南
自定义比较的明显示例是
System.String
(string
) - 它是引用类型,但与比较相关时表现为常规值类型。
回到原始示例:
IntegerPlus
是struct
,没有自定义“==”/Equals
:没有自动创建==
(new IntegerPlus(42) == new IntegerPluss(42)
- 语法错误)。您可以获得 Equals
(自动提供)的所有字段的值比较。IntegerPlus
是不提供自定义 class
或 operator ==
的 Equals
,您将获得参考比较和 new IntegerPlus(42) != new IntegerPluss(42)
,与 Equals
IntegerPlus
仅提供 ==
、!=
、Equals
之一,则行为将由自定义实现定义(外部观察者可能无法解释)IntegerPlus
是值类型或引用类型,并提供所有 4 个比较相关方法的一致集,您可以获得值比较行为在 Java 中,
==
运算符对于所有可编译的操作数组合都是安全的,并且只要操作数既不是 float
也不是 double
,它将实现等价关系。随着自动装箱的出现,这不再是正确的,因为不幸的是,原语与其包装的等效项之间的合法比较并不安全,并且以与单独类型定义的等价关系不一致的方式扩展了 ==
运算符。
虽然当两个操作数都是引用类型时 Java 将测试的等价关系(即引用等价)并不总是程序员感兴趣的,但 ==
的行为与引用类型一致。如果变量 x、y 和 z 是引用类型的任意组合,并且表达式 x==y、y==z 和 x==z 全部编译,则在其中两个为 true 的每种情况下,第三个也将是.在 C# 中,
==
标记用于表示两个不同的运算符:可重载相等测试和默认引用相等测试。如果
==
的操作数之一定义了适用于所提供操作数的特定组合的重载,则该标记将被解释为可重载的相等测试运算符。否则,如果操作数是兼容的引用类型,它将被解释为默认的引用相等测试运算符。由于两个运算符使用相同的标记,并且它们具有不同的语义,因此它通常无法在引用类型之间实现可靠的等价关系,除非所讨论的类型都没有重载它来表示除引用相等之外的任何内容。 给定定义
String s1=123.ToString(); String s2=123.ToString(); Object o = s1;
,比较
s1==s2
将返回True(使用
(string,string)
的
==
重载,它会看到它们包含相同的字符),并且
o==s1
将返回true(使用默认引用- 等价运算符以查看它们 是同一个对象),但
o==s2
将返回 false(使用默认的引用等价运算符来查看它们是不同的对象)。如果
==
的两个操作数都是
Object
类型,那么它将表现为引用相等测试;但是,如果它们是其他类型,则该运算符有时可能表现为引用相等测试,有时则表现为其他类型。