如何在C#中增加封装性?

4

最近我学习了C#,但是在C++中,我可以通过使用const修饰符,在将对象传递给方法时实现更好的封装。但是在C#中,对象可以通过引用参数进行修改,例如在Graphics对象上调用Dispose

有时我需要更多的封装。属性可以提供更好的解决方案。然而,我发现,例如对Form.Location属性进行修改,甚至对其X成员进行修改都是不允许的。尽管Form.Location是一个get; set;属性,但其成员不能被修改。我尝试使用一个{get; set;}属性来实现这一点,但仍然可以修改X成员。

当一个方法例如Dispose一个对象时,这也是一个问题。

如何在C#中实现更多的封装?


常量正确性是精神上的自慰。 - Ritch Melton
这里的一个重要点是引用类型和值类型。任何具有值语义的类型都应该是不可变的。 - CodesInChaos
我不明白这与封装有什么关系。听起来你正在尝试更新某种类型的公共属性上的X值,并遇到了问题? - Ritch Melton
@Ritch 嗯?!我从没想过我会听到这句话… - Paul Manta
@Paul - 这可能会变成聊天,但是就我而言,我认为它不能防止错误,并且“纯”const/mutable设计(如meyers等)只会增加冗长。 - Ritch Melton
1
我很惊讶这个问题有答案,因为我甚至都搞不清楚在问什么。 - Igby Largeman
3个回答

4

由于Form.Location是返回值类型(Point)的属性,因此您无法更改Form.LocationX属性。一旦访问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;
}

如果你想让一个对象可以被访问但不能被修改,你需要自己进行封装。例如,如果你希望类的使用者能够在你的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
这里有两篇文章讨论为什么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

将文本翻译成中文:

将类设计为不可变有时是解决问题的方法,但并不总是可行的选择,因为它仅适用于“类”级别,而不适用于方法级别。有时您可能需要公开类的成员变量,该变量不是不可变类型,因此可能会从外部进行修改。

最好的选择:接受这一点,在实践中,const-ness 的重要性往往被高估了。


1
你需要 Point { get; }。它是允许修改的 set

我知道 {get;}Form.Location 属性是 get; set; 类型的,其成员不能被修改。 - user586399
我认为TS只是将其用作示例,并希望他可以在多种情况下使用一种方法? - Frederik Gheysels

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接