Вопрос

Допустим, у меня есть свойство в классе:

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top