Как получить больше инкапсуляции в C #? - PullRequest
3 голосов
/ 24 сентября 2011

Я недавно выучил C # приблизительно. Однако в C ++ я мог бы реализовать лучшую инкапсуляцию при передаче объектов в методы с модификатором const. Но в C # объекты можно изменять с помощью ссылочного параметра, например Dispose для Graphics объекта.

Мне иногда нужно больше инкапсуляции. Свойства могут дать лучшее решение. Однако я обнаружил, что, например, изменение свойства Form.Location или даже его члена X не допускается. Хотя Form.Location является get; set; свойством, его члены не могут быть изменены. Я попытался сделать это со свойством Point {get; set;}, но я все еще могу изменить X member.

Это также проблема, когда метод, например, Dispose s объект, как упоминалось ранее.

Как я могу реализовать больше инкапсуляции в C #?

Ответы [ 3 ]

4 голосов
/ 24 сентября 2011

Вы не можете X свойство Form.Location, потому что Form.Location это свойство, которое возвращает тип значения (Point). Как только вы получите доступ к Form.Location, вы получите копию местоположения; таким образом, что-то менять в этой копии не имеет смысла. Поскольку this.Location.X = ... является очевидной ошибкой, компилятор C # не позволяет вам сделать это.

Вы можете, однако, заменить полное значение Form.Location, так как его установщик свойства равен public:

private void button1_Click(object sender, EventArgs e)
{
    // move window to the left edge of the screen
    this.Location = new Point(0, this.Location.Y);    
}

или, альтернативно,

private void button1_Click(object sender, EventArgs e)
{
    // move window to the left edge of the screen
    var loc = this.Location;
    loc.X = 0;               // yes, it's a mutable struct
    this.Location = loc;
}

Возвращаясь к исходному вопросу: если вы хотите сделать объект доступным, но не хотите, чтобы он был изменен, вам нужно будет инкапсулировать его самостоятельно. Например, если вы хотите, чтобы потребители вашего класса могли Draw на вашем Graphics объекте, но не хотели, чтобы они вызывали Dispose, вы просто не можете напрямую выставить объект Graphics. Вместо этого вам нужно обернуть каждый метод, который может вызывать потребитель:

// bad, consumer can do anything with the Graphics object
public Graphics Graphics
{
    get { return graphics; }
}

// good, consumer can only do specific stuff
public void Draw(...)
{
    graphics.Draw(...);
}
2 голосов
/ 24 сентября 2011

Вот две статьи, обсуждающие, почему в C # отсутствует модификатор "const":

http://blogs.msdn.com/b/ericgu/archive/2004/04/22/118238.aspx

http://blogs.msdn.com/b/slippman/archive/2004/01/22/61712.aspx

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

Лучший вариант: жить с этим, на практике важность константностичасто переоценивают.

1 голос
/ 24 сентября 2011

Вам нужно Point { get; }.Это set, который позволяет модификацию.

...