Справочный вопрос: когда два объекта равны?

2

У меня есть класс Vector, и я тестировал следующий unit test (используя 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 также указывать на ту же память, что и на 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");

Означает ли это, что, когда я использую новый оператор для определения нового объекта, старые назначения больше недействительны? Любое другое (или правильно - если я ошибаюсь) объяснение?

  • 0
    Эта поведенческая разница является обязательным программированием по сравнению с реактивным программированием
  • 0
    Майкл Грин: Нет, это разница между ссылкой и значением и тем, как реализован оператор '='.
Показать ещё 1 комментарий
Теги:
variable-assignment
reference-type

5 ответов

4
Лучший ответ

Линия

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

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

Напротив, линия

test2[1] = 4;

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

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

  • 0
    После test2 [1] = 4 вы увидите, что test1 [1] также будет равен 4.
  • 0
    Следует отметить, что test2 [1] = 4; также приведет к изменению test1 [1], так как они оба указывают на один и тот же объект. Так что, конечно, они все еще равны.
1

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

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

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

0

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

Отъезд http://msdn.microsoft.com/en-us/library/dd183752.aspx

0
Vector test1 = new Vector(new double[] { 6, 3, 4, 5 });

Создает два объекта, сам вектор и ссылку на него.

Представьте, что у вас есть список элементов на странице.

Когда вы используете new Vector, вы фактически пишете новую строку на странице, которая содержит вектор.

Объекты

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

У вас также есть список ссылок (Vector test1 = new Vector), которые ссылаются на первую страницу, и (test2 = test1)

Ссылки

  • test1- > 1
  • test2- > 1

когда вы говорите 'test2 = new Vector {5,4,3,2,1}, вы в конечном итоге получаете новый векторный объект на первой странице и меняете, к какому векторному тесту2 относится.

Объекты

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

Ссылки

  • test1 → 1
  • test2 → 2

В вашем втором примере тесты test1 и test2 все еще указывают на один и тот же объект, поэтому тест проходит.

0

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню