Why Private C# Variables are Not as Private as you Thought

Why Private C# Variables are Not as Private as You Thought

Private fields are not accessible outside the class. It’s C# 101 right?

Which means this code should not work…

But surprisingly…it does.

As it turns out…

Private variables are accessible from other objects of the same type. When you stop and think about it, it’s not as mad as it first seems. Why do we make a variable private? We do it to encapsulate the state of an object. We also do it to maintain control over the state the object.

A simple example could be if we were modeling a container with a limited capacity – like a box of chocolates. We could model this like so:

Can you spot the problem here? Even though we have an IsValid method, it’s still possible to add more than the maximum number of chocolates to the box (not that the customer would actually mind). To prevent this we can encapsulate the box. Then provide methods which enforce our constraints. A nice added extra is that we no longer need the IsValid method.

The assumption here is…

You cannot expect developers who are building other parts of the system to know how your thing (box in this case) works. Good tests, whether they be unit or integration will help here. The real value here is you can avoid misunderstandings in your code by making the implicit, explicit.

But if the developer is working within the class then they should know how the class works. You can then trust them to change the internal state – even of other classes of the same type!

I’m sure there are other good reasons why this quirk exists (if you know one add it to the comments). But I want to highlight one use which I’ve found particularly handy.

Access to Private Variables is Handy When Building Value Objects (VO)

One of the tactical patterns in Domain Driven Design is Value Objects (VO). By the way you don’t need to be doing DDD to use it. It’s defining feature is that it’s equatable by it’s value rather than by id.

A common example is a string. If I create two strings with the same characters in the same order and the same case then they are equal to each other by value.

Another example could be a ‘telephone number’ in a CRM. One number is equal to another by value. Unless you happen to be writing software for a telephone company. In which case the telephone number could potentially be the customer id and therefore not a VO.

More often than not a VO is immutable. That is, once it’s created you can’t change it’s value. This is the case for our string example. When you ‘change’ a string you are actually creating a new object.

Back to the point. Why is it helpful to be immutable?

I can think of 4 reasons:

  1. It’s much easier to test an object which can’t change
  2. It’s easier to parallelise an immutable object
  3. It’s easier to ensure it is always in a valid state
  4. You don’t need to keep track of many id’s in you application *

* is probably the biggest reason.

An Example Value Object

To illustrate a value object lets model a fluid container – otherwise known in our domain as a cup. Each cup has a maximum capacity of 1l. We can decant the content of 1 cup into another*. Any liquid over the max volume is lost. A cup is considered equal to another cup depending on the volume of liquid it contains.
* from a code perspective, this results in another instance of cup.

Let’s start with some tests…

How do we construct a cup? Because we want to make our cup immutable let’s pass in the current volume of liquid into the constructor. So our first rather simplistic test could be to ensure we can construct a cup with a volume of liquid.

New we can get to the interesting part. How do we ensure they are equal? This is where we can take advantage of the access to private variables.

I’ll leave the ‘Decant’ method as an exercise for you. Interesting question though, what happens to the cup when you decant the liquid out of it? It is after all immutable 😉

Conclusion

Value Objects are a useful construct in Domain Driven Design. When overriding the equals method, you can take advantage of this ‘quirk’ in C#. The quirk is you can access private variables of another class of the same type.

I hope you found this little tip handy. Leave a comment and let me know.

P.S. I’ve created a code kata based designed to be used to illustrate VO’s. It works well as a team exercise. Download it here:

DOWNLOAD THE COLOUR MIXER CODE KATA

Daniel

I'm a professional software engineer of near on 15 years. Lucky enough to work for a small but rapidly growing company in London called Redington. They have given me the technical freedom to learn some cutting edge technologies like CQRS and Event Sourcing. Now I'm sharing what I learn here.

17 thoughts on “Why Private C# Variables are Not as Private as you Thought

  1. pete says:

    Equality check is a good point, without this “feature” overriding Equals would easily turn into a painful task.
    BTW. This exact privacy “feature” is described in Bart De Smet’s “C# Unleashed” – great book, highly recommended.

  2. […] Why Private C# Variables are Not as Private as you Thought (Daniel Whittaker) […]

  3. Good read and a nice little feature!

    Regardin “Unless you happen to be writing software for a telephone company. In which case the telephone number could potentially be the customer id and therefore not a VO.” I disagree. In this scenario, the customer is an entity and not a value object, but the ID of the customer itself should always be a value object. The ID cannot change, so it is immutable, and as such also equatable to other ID:s. It’s actually quite good convention to explicitly create separate ID classes to represent the ID:s of other entities, as then changing the ID or managing the equality is easy.

    • Daniel says:

      Ah – my mistake, it was supposed to read ‘line id’ as in the specific telephone line. But you make an interesting point nonetheless.

  4. dotnetchris says:

    I think you have a major recurrent flaw in this post. You meant private FIELD, not variable.

    I wouldn’t doubt you could access variables from another method… somehow… I was actually interested in seeing that happen here. You really need to edit your post ctrl+f variable and replace with field pretty much.

  5. […] Why Private C# Variables are Not as Private as you Thought – Daniel Whittaker […]

  6. The overall idea with this feature comes from C++. For example, copy constructors in C++ need to have access to private fields in order to deep copy the object. Your example with overriding the Equals method is also a good justification for this feature to exist.

  7. “from other classes of the same type” – can you give me an example of two different classes with same CLR type?

    • Daniel says:

      Corrected – that should read “objects of the same type”. I don’t think it works with inherited types.

  8. This is similar in concept to making a static factory method on a class. The factory method can still do what is necessary to create an instance. You might have some more complex logic that you only want at creation time and you want to prevent a public creation to make it obvious that this complex logic might exist (or you want to then create a singleton using a private static variable). Anything defined within the class has access to the properties/methods within the class and any instances of that class.

    public class TestObject
    {
    private currentTime DateTime;

    private TestObject() {}

    public static TestObject CreateInstance()
    {
    var obj = new TestObject();
    obj.currentTime = DateTime.Now;
    return obj;
    }

    private static TestObject singleton;

    public static TestObject GetSingletonInstance()
    {
    if(singleton == null)
    singleton = CreateInstance();

    return singleton;
    }
    }

  9. freekpaans says:

    The “quirk” exists to enable certain performance optimizations. Being able to look inside other objects internals will in general allow for certain operations to be carried out faster than when you need to go through its public interface. It’s at the heart of the difference between Abstract Data Types and objects, see for example http://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf.

  10. […] Adventures in String Concatenation: Introducing String Interpolation – Rion Williams() Why Private C# Variables are Not as Private as you Thought – Daniel Whittaker Null Object Pattern – (DevIQ) Using Lazy and […]

Comments are closed.