【问题标题】:Reference question: when are two objects equal?参考问题:两个对象何时相等?
【发布时间】:2011-01-02 08:55:44
【问题描述】:

我有一个 Vector 类,我正在测试以下单元测试(使用 nUnit)。

1  Vector test1 = new Vector(new double[] { 6, 3, 4, 5 });
2  Vector test2 = test1;
3  Assert.AreEqual(test1, test2, "Reference test");
4  test2 = new Vector(new double[] { 3, 3, 4, 5 });
5  Assert.AreEqual(test1, test2, "Reference test");

第 3 行的第一个测试通过,但第 5 行的第二个测试失败。既然我在第 2 行做了赋值语句,那么 test2 不应该也指向与 test1 相同的内存吗?我的 Vector 被定义为一个类,所以它是一个引用类型。另一方面,以下测试通过:

1  Vector test1 = new Vector(new double[] { 6, 3, 4, 5 });
2  Vector test2 = test1;
3  Assert.AreEqual(test1, test2, "Reference test");
4  test2[1] = 4;
5  Assert.AreEqual(test1, test2, "Reference test");

这是否意味着,当我使用 new 运算符定义新对象时,旧的赋值不再有效?任何其他(或正确的 - 如果我错了)解释?

【问题讨论】:

  • 这种行为差异是命令式编程反应式编程
  • Michael Greene:不,这是引用和值之间的区别,以及“=”运算符的实现方式。
  • 哇!!这很快 - 感谢所有的答案。

标签: c# .net variable-assignment reference-type


【解决方案1】:

线

test2 = new Vector(new double[] { 3, 3, 4, 5 });

在堆上创建Vector 的新实例并将其地址分配给test2 变量。 test2 之后将指向一个新的、完全不同的对象。

相比之下,这条线

test2[1] = 4;

不会改变test2 变量本身(它是对堆上某个对象的引用)。相反,它正在改变它指向的对象。 test2 仍然指向堆上的相同位置。

总而言之,在前者中,您正在更改 reference,而在后者中,您正在更改 referent

【讨论】:

  • 在 test2[1] = 4 之后,您会看到 test1[1] 也将等于 4。
  • 需要指出的是test2[1] = 4;也会导致 test1[1] 改变,因为它们都指向同一个对象。所以当然他们仍然是平等的。
【解决方案2】:

当你分配一个变量时:

test2 = new Vector(new double[] { 3, 3, 4, 5 });

您正在将 test2 的值更改为赋值运算符右侧返回的新引用。当然,这里返回的引用与test1 中的引用不同,因为它是调用构造函数的单独情况,并且引用不可能相同,因为 Vector 是用不同的参数构造的。

【讨论】:

    【解决方案3】:

    是的,当您使用 new 运算符定义新对象时,旧的赋值不再有效。

    你的向量是一个引用类型,但是当你说 test2 = something 你说“现在 test2 指向别的东西”。

    顺便说一句,如果您希望将具有相同内部值的两个不同 Vector 对象视为相等,您可以通过在 Vector 类上实现 IEquatable 来实现,但这是另一个问题...

    【讨论】:

      【解决方案4】:

      Equals 比较值以查看它们是否匹配,而如果要比较引用,则需要使用 ReferenceEquals

      查看http://msdn.microsoft.com/en-us/library/dd183752.aspx

      【讨论】:

        【解决方案5】:
        Vector test1 = new Vector(new double[] { 6, 3, 4, 5 });
        

        正在创建两个对象,向量它的自身和对它的引用。

        假设您在页面上有一个项目列表。

        当您使用new Vector 时,您实际上是在包含向量的页面上写了一个新行。

        对象

        1. {1,2,3,4,5}

        您还有一个引用列表 (Vector test1 = new Vector) 引用第一页,以及 (test2 = test1)

        参考文献

        1. test1-> 1
        2. test2-> 1

        当您说“test2 = new Vector {5,4,3,2,1}”时,您最终会在第一页上看到一个新的向量对象,并更改 test2 所指的向量。

        对象

        1. {1,2,3,4,5}
        2. {5,4,3,2,1}

        参考文献

        1. test1 -> 1
        2. test2 -> 2

        在您的第二个示例中,test1 和 test2 仍然指向同一个对象,这就是测试通过的原因。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-01-17
          • 2014-01-02
          • 1970-01-01
          • 2022-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多