Question

Here is a very simple question, which I'm still very uneasy about:

Why is it widely accepted now for a class to return a reference to its private member through an accessor method? Doesn't this totally break the encapsulation principle? If this is OK, then why not just make the member public!?

public class EncapsulationViolator
{
  private object abuseMe;

  public object AbuseMe 
  {
    get { return abuseMe; }
  }
}

Edit The case I was considering is this

EncapsulationViolator ev = new EncapsulationViolator();

object o = ev.AbuseMe;

o.SetValue(newValue);

Now ev's state has change through transitivity because its member abuseMe's state has changed.

In the context of DDD, this is not OK if the object is an Aggregate Root. I quote

Allow external objects to hold references to the root only. Transient references to internal members can be passed out for use within a single operation only. Because the root controls access, it cannot be blindsided by changes to the internals.

[Domain-Driven Design, Eric Evans]

... setters schmetters ...

Was it helpful?

Solution

You're conflating the C++ term "reference" with the fact that C# passes objects by value (of their reference).

In this case the caller of the getter AbuseMe cannot swap out the private field abuseMe. Thus, there is no violation of encapsulation.

EncapsulationViolator x = new EncapsulationViolator();
object y = x.AbuseMe;
y = 17; // I have not changed x.AbuseMe

Debug.Assert(y != x.AbuseMe); // Passes!

Furthermore, property getters and setters allow for proper encapsulation of private fields and is functionally identical to implementing these as methods (in fact they are implemented as methods by the compiler).

One case in which returning a private variable could break encapsulation is when you return a reference to an array:

class X
{
    private int[] amazing = new int[10];

    public int[] Amazing { get { return this.amazing; } }
}

X a = new X();
int[] x = a.Amazing;
int[] y = a.Amazing;

x[2] = 9;
Debug.Assert(x[2] != y[2]); // Fails!

OTHER TIPS

It depends on what kind of object the member is. If it for example is a string, then it's immutable, so you can't change the string.

If it is a mutable object, you can change the content of the object from outside the class, but you can't replace the object itself.

If the object should not be possible to change from outside the class, the getter should return an immutable version of the object.

The pattern could break the encapsulation if you do it wrong, but done correctly the encapsulation is intact.

I don't think it breaks encapsulation. The class still decides where the return value of AbuseMe comes from. It could come from a different member, or it could be recreated or copied every time.

Point is that the class decides what it allows users to do with that member (get/set or both and their visibility), it can perform validation and prevent invalid values to be set, and the users don't need to know where that value comes from.

Also, if you want to add custom logic to the get/set methods, you can do so without breaking compatibility with other assemblies.

It's just syntactic sugar. It's not any different from Java's getXXX and setXXX methods.

The point of the getter and setter is specifically to enforce encapsulation. The whole point is that you don't give access directly to the object, but force it to be accessed by a function that you define. Getters and setters ARE encapsulation. If you decide to just return the object, well that's your business but you aren't allowing direct access without hitting the getter.

Read this: http://en.wikipedia.org/wiki/Mutator_method

IMO - too many answers here are promoting getters/setters. Getters/setters are great for procedural code, you either do some calculation and set the result or grab the value(s) and make some decision.

A well known principle in OO programming is Tell don't ask which basically says you shouldn't ask an object of its internal state to make a decision.

That being said, I use accessors/properties myself. However, when possible, I try to avoid them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top