Справочный вопрос: когда два объекта равны? - PullRequest
2 голосов
/ 07 января 2010

У меня есть класс 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 не проходит. Разве test2 также не должен указывать на ту же память, что и test1, так как я сделал оператор присваивания в строке 2? Мой Вектор определен как класс, поэтому это ссылочный тип. С другой стороны, следующие тесты проходят:

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 для определения нового объекта, старые назначения больше не действительны? Любое другое (или правильное - если я ошибаюсь) объяснение?

Ответы [ 5 ]

4 голосов
/ 07 января 2010

Линия

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

создает новый экземпляр Vector в куче и присваивает его адрес переменной test2. test2 будет указывать на новый, совершенно отдельный объект после этого.

В отличие от линии

test2[1] = 4;

не изменяет саму переменную test2 (которая является ссылкой на некоторый объект в куче). Скорее, это меняет объект, на который он указывает. test2 все еще относится к тому же месту в куче.

Итак, в первом случае вы меняете ссылку , в то время как в последнем вы изменяете референт .

1 голос
/ 07 января 2010

Когда вы присваиваете переменную наподобие:

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

Вы изменяете значение test2, чтобы оно стало новой ссылкой, возвращаемой правой частью оператора присваивания. Конечно, возвращаемая здесь ссылка отличается от ссылки в test1, потому что это отдельный случай вызываемого конструктора, и ссылки не могут быть одинаковыми, поскольку вектор создается с разными аргументами. *

0 голосов
/ 07 января 2010
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 по-прежнему указывают на один и тот же объект, поэтому тест проходит успешно.

0 голосов
/ 07 января 2010

Equals сравнивает значения, чтобы увидеть, совпадают ли они, а если вы хотите сравнить ссылки, вам нужно использовать ReferenceEquals.

Выезд http://msdn.microsoft.com/en-us/library/dd183752.aspx

0 голосов
/ 07 января 2010

Да, когда вы используете оператор new для определения нового объекта, старые назначения больше не действительны.

Ваш вектор является ссылочным типом, но когда вы говорите test2 = что-то, что вы говорите "теперь test2 указывает на что-то другое".

Кроме того, если вы хотите, чтобы два разных объекта Vector с одинаковыми внутренними значениями считались равными, вы можете получить это, реализовав IEquatable в своем классе Vector, но это другой вопрос ...

...