我是C#和.Net的新手,所以这可能是一个天真的问题。但无论如何,请考虑这个C#代码:
class A {
public int Data {get; set;}
}
class B {
public A Aval {get; set;}
}
上面的B.Aval属性返回对其内部A对象的引用。作为一名前C ++程序员,我发现这很危险,因为通过公开引用成员对象类B违反了数据隐藏的原则。尽管如此,这似乎是C#世界的常规做法。
我的问题是,如果有的话,为什么这样的设计是通常的方法,而不是返回内部成员的副本,这在很多方面会更安全(包括线程安全的情况)?
我理解即使在C ++中,有时候好的设计也要求你直接暴露类成员(带引擎和立体声对象的 Car 类在脑海中浮现出来,但它似乎不是C#中的标准。
答案 0 :(得分:2)
你是绝对正确的 - 你应该只从对象是不可变的属性中返回对象,或者你很高兴调用者可以将它们修改到任何程度。一个典型的例子就是返回集合 - 通常最好在集合中返回一个只读包装,而不是直接返回“真实”集合。
另一方面,实用主义有时要求将其记录为“请不要更改返回的对象” - 特别是当它是仅在公司内使用的API时。
希望在未来的C#和.NET版本中能够获得更多的不变性支持,这将使这更容易应对 - 但在许多情况下它可能仍然是一个棘手的问题。
答案 1 :(得分:1)
这不是封装 - 它是通过对象组合或聚合进行抽象的行为,具体取决于内部对象生命周期的创建/管理方式。
在合成模式中,访问复合状态是完全可以接受的。 B实例中的A实例。
正如您所指出的,封装的语义非常不同 - 完全隐藏A的内部实现,例如:通过从A继承B.
答案 2 :(得分:1)
这可能与Law of Demeter有关...你是否只谈论没有额外逻辑的getter和setter(从而有效地直接暴露成员),或任何get-set对?在任何情况下,如果外部对象的状态的这部分没有参与外部对象的有意义的不变量,我认为这样做不一定是不合理的。