C # and hiding data

I'm new to C # and .Net in general, so this might be a naive thing to ask about. 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 returns a reference to its internal object A. As a former C ++ programmer, I find it dangerous because by exposing the reference to a member object of class B, the principle of data hiding is violated. However, this seems to be common practice in the C # world.

My question is, if this is the case at all, why is such a design the usual approach rather than returning copies of inner members, which would be much safer in many ways (including in the case of thread safety)?

I understand that even in C ++ sometimes good design requires you to render the members of the class yourself (a Car class with Engine and Stereo objects inside it comes to mind), but this is not the norm as it seems in C #.


source to share

3 answers

You are absolutely correct - you only need to return objects from properties where the object is immutable, or you are happy that the caller can change it in some way. Returning collections is a classic example of this — it is often far better to return a read-only wrapper around a collection than to directly return the "real" collection.

On the other hand, pragmatism sometimes only requires documenting this as "please do not change the returned object", especially when it is an API that is only used by the company.

Hopefully there will be more immutability support in future versions of C # and .NET, making it easier to work with - but it can remain a knotty problem in many cases.



This is not encapsulation - it is an act of abstraction through composing or aggregating objects depending on how the lifetimes of the inner object are created / managed.

In composition templates it is perfectly acceptable to access the composite state, for example. instance A in instance B.


As you note, the semantics of encapsulation are very different - hiding the internal implementation of A completely, for example. inheriting B from A.



Perhaps it has something to do with the Law of Demeter ... are you only talking about getters and setters that have no additional logic (and thus effectively expose an element directly) or any pairs with a given set? In any case, if this part of the state of the external object does not participate in sinister invariants on the external object, I do not consider it unreasonable to do so.



All Articles