В C# у меня есть простой 3D векторный класс.
static void Main(string[] args)
{
Vector3D a, b;
a = new Vector3D(0, 5, 10);
b = new Vector3D(0, 0, 0);
b = a;
a.x = 10;
Console.WriteLine("vector a=" + a.ToString());
Console.WriteLine("vector b=" + b.ToString());
Console.ReadKey();
}
вывод,
векторизуйте = 10, 5, 10
вектор b = 10, 5, 10
Я присваиваюсь, прежде чем я изменю a.x на 10. Таким образом, я ожидал
векторизуйте = 10, 5, 10
вектор b = 0, 5, 10
Из того, что я понимаю =, оператор присваивает ссылку для возражения как указатель? И в C# я не могу перегрузиться = оператор.
Я должен вручную присвоить каждое свойство?
Да, поскольку Vecor3D относится к классу , это совершенно правильно.
Классы являются ссылочными типами, и ваш оператор b = a;
копирует не экземпляр Vector3D, а ссылку на экземпляр.
Если вы хотите «клонировать» экземпляры, вы можете добавить интерфейс IClonable, но от этого более или менее отказались.
Лучшее решение для типа
могло бы состоять в том, чтобы сделать его структурой. Структуры - это типы значений, и значение b = a;
изменится (в сторону желаемого).
3D-точка соответствует всем критериям структуры (маленькая, без идентичности). Предпочтительный способ - сделать его неизменным.
Да, « = оператор назначает ссылку на объект как указатель », как вы выразились. Таким образом, и a
, и b
ссылаются на один и тот же одиночный объект в памяти. (Объект, на который ранее ссылался b
, больше не упоминается и будет собираться мусором.)
Есть несколько способов решить эту проблему:
Сделайте Vector3D
a struct вместо класса.Структуры являются типами значений вместо ссылочных типов, поэтому b = a
копирует содержимое a
в переменную b
.
Реализуйте метод Clone
в своем классе Vector3D
(ранее это означало реализацию ICloneable
, но это больше не рекомендуется ). В качестве альтернативы вы можете создать конструктор Vector3D
, который принимает другой вектор в качестве параметра и создает копию.
Вручную скопируйте три значения самостоятельно ( b = new Vector3D (a.x, a.y, a.z)
), если вы не можете изменить реализацию Vector3D
.
Возможно, вы захотите изменить свой класс Vector3D
на struct. Это позволит вам работать с типом значений вместо ссылочного типа.
Другой вариант - реализовать ICloneable
или использовать какой-нибудь другой метод для создания глубокой копии вашего объекта.
Да, ссылочные типы присваиваются по ссылке.
Если вы хотите иметь отдельный экземпляр, вам нужно CLONE ваш экземпляр.
Создайте метод Vector3D.Clone(), который будет выглядеть примерно так:
public Vector3D Clone()
{
return new Vector3D(this.x, this.y, this.x);
}
Тогда ваш Main должен выглядеть так:
static void Main(string[] args)
{
Vector3D a, b;
a = new Vector3D(0, 5, 10);
b = new Vector3D(0, 0, 0);
b = a.Clone();
a.x = 10;
Console.WriteLine("vector a=" + a.ToString());
Console.WriteLine("vector b=" + b.ToString());
Console.ReadKey();
}
Но, как говорили другие, что-то такое маленькое, как Vector3D, лучше использовать как неизменяемую структуру
.Вы можете сделать его структурой, как говорит Хенк. И вы можете добавить конструктор
struct Vector3D
{
public int x;
public int y;
public int z;
public Vector3D(int x, int y, int z)
{
this.x = x;
this.y = y;
this.z = z;
}
public override string ToString()
{
return string.Format("{0}, {1}, {2}", x, y, z);
}
}
Вы также можете сделать это без добавления конструктора.
b = new Vector3D() {x=0, y=0, z=0};
Нет необходимости использовать struct
, я предлагаю вам разработать свой Vector3D
как неизменяемый класс. Вот несколько хороших примеров. Конечно, a.x = 10
невозможно для неизменяемого класса.