我试着理解这段代码:
double b = 3;
object o = b;
Console.WriteLine(o.Equals(3));//false
Console.WriteLine(o.Equals(b));//true
Console.WriteLine( o == (object)b );//false
o.Equals(b)
为true
? Equals
未检查引用,为什么o.Equals(3)
为false
? 感谢。
答案 0 :(得分:5)
Equals
检查值相等,而不是引用相等。 o
和b
都相同:double
,其值为3.0
。3
这里是int
,而不是double
,Equals
对于不同的类型不进行任何转换以使它们兼容,就像编译器通常一样这样做。 o.Equals(3.0)
将返回true
。答案 1 :(得分:2)
double b = 3;
在堆栈中创建一个值为3
的新变量object o = b;
在堆中创建一个对象,该对象在堆栈中引用b
的相同位置,因此您有两个引用的相同变量 这是装箱 < / p>
o.Equals(3)
是假的,因为它会创建一个新的匿名变量,其值为3 而不是b
o.Equals(b)
是真的,因为它是相同的变量
o == (object)b
为false,因为==
正在比较内存中的引用 addresess ,但Equals
会比较变量本身的值
答案 2 :(得分:0)
参见this 它解释了关于平等行为的所有内容。
答案 3 :(得分:0)
每次尝试将值类型转换为引用类型时,都必须将其装箱到新的对象实例。在不破坏兼容性的情况下,系统无法做任何其他事情。除此之外,虽然人们可能期望盒装值类型是不可变的(*),但它们都不是。 每个值类型在装箱时会产生一个可变对象。虽然C#和vb.net没有提供任何方便的方法来改变这些对象,但用C ++ / CLI编写的可信和可验证的代码可以很容易地完成。即使系统知道堆对象持有Int32
,其值目前为23,语句Object foo = 23;
也必须生成一个值为23的新Int32
堆对象,因为系统无法知道是否有什么东西可能计划将现有对象的值更改为57.
(*)我认为他们应该是;而不是让所有盒装对象都可变,最好提供一种方法,像List<T>.Enumerator
这样的结构类型可以指定可自定义的装箱行为。我不确定现在是否有任何方法可以解决这个问题而不会完全破坏与现有代码的兼容性。