4

我试着理解这段代码:

double b = 3;
object o = b;
Console.WriteLine(o.Equals(3));//false
Console.WriteLine(o.Equals(b));//true
Console.WriteLine( o == (object)b );//false
  1. 每个新的拳击都对对象 b 进行不同的引用?
  2. 如果 1. 是真的,为什么o.Equals(b)true
  3. 如果Equals不检查引用,为什么o.Equals(3)false

谢谢。

4

4 回答 4

5
  1. 是的,每次对值类型进行装箱时,都会创建一个新对象。更多关于拳击在这里。
  2. Equals检查值相等,而不是引用相等。两者ob是相同的: adouble的值为3.0
  3. 3这里是a ,而int不是 a double,并且Equals对于不同的类型不会进行任何转换以使它们兼容,就像编译器通常做的那样。o.Equals(3.0)将返回true
于 2012-11-29T08:55:24.787 回答
2
double b = 3;

在堆栈中创建一个值为 3 的新变量

object o = b;

在堆中创建一个对象,该对象引用b堆栈中的相同位置,因此您具有具有两个引用的相同变量 这是装箱

o.Equals(3)

为假,因为它创建了一个 值为 3而不是 b的新匿名变量

o.Equals(b) 

是真的,因为它是同一个变量

o == (object)b

为假,因为==正在比较内存地址中的引用,比较Equals变量本身的值

于 2012-11-29T08:59:28.560 回答
0

看到这个 它解释了关于等于行为的所有内容。

于 2012-11-29T08:52:18.503 回答
0

每次尝试将值类型转换为引用类型时,都必须将其装箱到新的对象实例中。在不破坏兼容性的情况下,系统无法做任何其他事情。除此之外,虽然人们可能期望装箱的值类型是不可变的(*),但它们都不是。 每个值类型在装箱时都会产生一个可变对象。虽然 C# 和 vb.net 没有提供任何方便的方法来改变这些对象,但用 C++/CLI 编写的可信且可验证的代码可以轻松做到这一点。即使系统知道一个堆对象包含一个Int32当前值为 23 的值,该语句Object foo = 23;也必须生成一个新的Int32堆对象的值为 23,因为系统无法知道是否有什么东西可能计划将现有对象的值更改为 57。

(*)我认为他们应该是;与其使所有的装箱对象都可变,不如提供一种方法来让结构类型(如List<T>.Enumerator可以指定可定制的装箱行为)更好。不过,我不确定现在是否有任何方法可以在不完全破坏与现有代码的兼容性的情况下解决这个问题。

于 2012-12-07T23:42:16.600 回答