Проблема с получателем / установщиком C #
-
21-09-2019 - |
Вопрос
Допустим, у меня есть свойство в классе:
Vector3 position{get; set;}
Итак, я где-то создаю экземпляр этого класса, и теперь я хочу изменить position.x, что сейчас было бы невозможно, потому что получатель и установщик устанавливают и получают весь объект.Поэтому я должен заставить временный Вектор3 изменить свои значения, а затем назначить его.
Обычно я бы сделал position общедоступным полем, чтобы эта проблема была решена.Но я не могу сделать это в данном случае, потому что position - это реализация интерфейса, а интерфейсы не могут иметь полей.
Итак, как я могу решить эту проблему наилучшим образом?
Редактировать:Vector3 - это структура, поэтому это тип значения
Решение
ИМО, самый простой ответ здесь:
private Vector3 position;
public Vector3 Position {
get {return position;}
set {position = value;} // with @Mehrdad's optimisation
}
public float X {
get {return position.X;}
set {position.X = value;}
}
public float Y {
get {return position.Y;}
set {position.Y = value;}
}
public float Z {
get {return position.Z;}
set {position.Z = value;}
}
Теперь вы можете измениться obj.X
, obj.Y
и obj.Z
если вам нужно изменить только одно измерение или изменить obj.Position
чтобы все изменить.
Если вам нужно имя position
чтобы реализовать интерфейс, затем сделайте это явно:
Vector3 IWhateverInterface.position {
get {return position;}
set {position = value;}
}
Другие советы
Является ли простое решение каким-то образом неприемлемым?
foo.position = new Vector(newX, foo.position.Y, foo.position.Z);
Что в этом плохого?Это кажется совершенно простым.
Это одна из проблем, связанных с изменяемыми типами значений.Вы можете создать новый экземпляр типа значения с новым X
значение и переназначение свойства.Вы можете упростить создание экземпляра, предоставив полезные конструкторы или добавив методы, которые возвращают измененный объект (вместо изменения значения).
Предварительно-P.S.: Слишком поздно увидел , что Vector3
является типом значения;поэтому следующий пост не сильно поможет.Извините за эту ошибку.
Что ж, хотя интерфейсы не могут иметь полей, они может обладают свойствами, например:
interface IVector3
{
double X { get; set; }
double Y { get; set; }
double Z { get; set; }
}
В вашем Vector3
, вы просто реализуете их , как и все остальное:
class Vector3 : IVector3
{
double IVector3.X
{
get { ... }
set { ... }
}
...
}
Теперь вернемся к вашему position
собственность.Вы привязываете свойство к фиксированному экземпляру во время инициализации и предоставляете только средство получения:
Vector3 position
{
get
{
return _position;
}
}
private Vector3 _position = new Vector3(...);
Сделав свойство доступным только для чтения (т.е.нет установщика), вы гарантируете, что он не будет заменен новым Vector3
объект.Вместо этого вы привязываете его к фиксированному экземпляру (_position
) во время инициализации.Но вы можете изменить Vector3
путем присвоения новых значений position.X
, position.Y
, или position.Z
.