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