简体   繁体   中英

C# and Data Hiding

I'm new to C# and .Net in general so this may be a naive thing to ask. But anyway, consider this C# code:

class A {
    public int Data {get; set;}
}

class B {
    public A Aval {get; set;}
}

The B.Aval property above is returning a reference to its internal A object. As a former C++ programmer, I find this dangerous because by exposing reference to an member object class B violates the principle of data hiding. Nonetheless, this seems to be the normal practice in the C# world.

My question is, if it is at all, why is such a design the usual approach as opposed to returning copies of internal members, which will be much safer in so many ways (including the case of thread safety)?

I understand that even in C++ sometimes good design demands that you do expose class members directly (a Car class with Engine and Stereo objects inside it comes to mind), but it is not the norm as seems to be in C#.

You're absolutely right - you should only return objects from properties where either the object is immutable, or you're happy for the caller to modify it to whatever extent they can. A classic example of this is returning collections - often it's much better to return a read-only wrapper round a collection than to return the "real" collection directly.

On the other hand, pragmatism sometimes calls for just documenting this as "please don't change the returned object" - particularly when it's an API which is only used within a company.

Hopefully there'll be more support for immutability in future versions of C# and .NET, which will make this easier to cope with - but it's likely to remain a knotty problem in many cases.

This isn't encapsulation - it's an act of abstraction through object composition or aggregation depending on how the internal object lifetimes are created/managed.

In composition patterns it is perfectly acceptable to access composite state eg the instance of A in the instance of B.

http://en.wikipedia.org/wiki/Object_composition

As you point out the semantics of encapsulation are very different - to completely hide the internal implementation of A eg by inheriting B from A.

This is maybe related to the Law of Demeter ... are you talking only about getters and setters that have no extra logic (and thus effectively directly expose the member), or any get-set pairs? In any case, if this portion of the outer object's state doesn't participate in meaninful invariants on the outer object, I don't think it's necessarily unreasonable to do this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM