У меня есть класс 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");
Означает ли это, что, когда я использую новый оператор для определения нового объекта, старые назначения больше недействительны? Любое другое (или правильно - если я ошибаюсь) объяснение?
Линия
test2 = new Vector(new double[] { 3, 3, 4, 5 });
создает новый кусок Vector
в куче и присваивает свой адрес переменной test2
. test2
после этого укажет на новый, полностью отличный объект.
Напротив, линия
test2[1] = 4;
не изменяет сама переменная test2
(которая является ссылкой на некоторый объект в куче). Скорее, он меняет объект, на который он указывает. test2
по-прежнему относится к тому же месту в куче.
Подводя итог, в первом вы меняете ссылку, а в последнем вы изменяете референт.
Когда вы назначаете переменную типа:
test2 = new Vector(new double[] { 3, 3, 4, 5 });
Вы изменяете значение test2 как новую ссылку, возвращаемую правой стороной оператора присваивания. Конечно, возвращаемая здесь ссылка отличается от той, что находится в test1
, потому что это отдельный случай вызываемого конструктора, и ссылки не могут быть одинаковыми, так как вектор строится с разными аргументами.
Equals
сравнивает значения, чтобы увидеть, соответствуют ли они, тогда как если вы хотите сравнить ссылки, вам нужно использовать ReferenceEquals
.
Отъезд http://msdn.microsoft.com/en-us/library/dd183752.aspx
Vector test1 = new Vector(new double[] { 6, 3, 4, 5 });
Создает два объекта, сам вектор и ссылку на него.
Представьте, что у вас есть список элементов на странице.
Когда вы используете new Vector
, вы фактически пишете новую строку на странице, которая содержит вектор.
Объекты
У вас также есть список ссылок (Vector test1 = new Vector), которые ссылаются на первую страницу, и (test2 = test1)
Ссылки
когда вы говорите 'test2 = new Vector {5,4,3,2,1}, вы в конечном итоге получаете новый векторный объект на первой странице и меняете, к какому векторному тесту2 относится.
Объекты
Ссылки
В вашем втором примере тесты test1 и test2 все еще указывают на один и тот же объект, поэтому тест проходит.
Да, когда вы используете новый оператор для определения нового объекта, старые назначения больше не действительны.
Ваш вектор является ссылочным типом, но когда вы говорите test2 = что-то, что вы говорите "теперь test2 указывает на что-то еще".
Если вы хотите, чтобы два разных объекта Vector с одинаковыми внутренними значениями считались равными, вы можете получить это, выполнив IEquatable в своем классе Vector, но этот другой вопрос...