C # проблема получения / установки - PullRequest
3 голосов
/ 18 января 2010

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

Vector3 position{get; set;}

Итак, я где-то создаю экземпляр этого класса, и теперь я хочу изменить position.x, что сейчас было бы невозможно, потому что метод get и set устанавливают и получают весь объект. Поэтому я должен сделать временный Vector3 изменить его значения, а затем назначить его.

Обычно я бы сделал положение открытым полем, чтобы проблема была решена. Но я не могу сделать это в этом случае, потому что позиция - это реализация интерфейса, а у интерфейсов не может быть полей.

Так, как я могу решить это лучшим способом.

Редактировать: Vector3 является структурой, поэтому ее тип значения

Ответы [ 4 ]

9 голосов
/ 18 января 2010

Простое решение как-то неприемлемо?

foo.position = new Vector(newX, foo.position.Y, foo.position.Z);

Что с этим не так? Это кажется совершенно простым.

5 голосов
/ 18 января 2010

ИМО, самый простой ответ здесь:

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;}
}
2 голосов
/ 18 января 2010

Это одна из проблем с изменяемыми типами значений. Вы можете создать новый экземпляр типа значения с новым значением X и переназначить свойству. Вы можете упростить создание экземпляра, предоставив полезные конструкторы или добавив методы, которые возвращают измененный объект (вместо изменения значения).

0 голосов
/ 18 января 2010

Pre-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.

...