C# Encapsulation – Do Auto-Implemented Properties Violate It?

cencapsulationobject-orientedproperties

In C#, when a field getting or setting requires logic, we use properties. For example:

private int _age;
public int Age
{
    get
    {
        Console.Writeline("Club member is {0} years old", _age);
    }
    set
    {
        if(value > 0 && value < 120)
        {
            _age = value;
        }
        else
        {
            Console.Writeline("We do not accept unborns nor immortals to our club.");
        }
    }
}

When no logic is required, we could use the very concise auto-implemented properties:

public string Name {get; set;}

Thos are very similar to public fields since you could read and change their values from anywhere. There are, however, some differences, as Michael Stum summarizes very well Jeff Atwood's article:

  • Reflection works differently on variables vs. properties, so if you rely on reflection, it's easier to use all properties.
  • You can't databind against a variable.
  • Changing a variable to a property is a breaking change. For example:

    TryGetTitle(out book.Title); // requires a variable
    

As I see it, those are very technical differences: public fields have some advantages over auto-implemented properties and vice-versa, but fundamentally, in an OOP point-of-view, they are very similar: fields which can be changed from any class, and that, as far as I know, violates encapsulation.

So why public fields considered evil due to the encapsulation violation while auto-implemented properties are so great?

Best Answer

The Question

The question is

So why public fields considered evil due to the encapsulation violation while auto-implemented properties are so great?

The answer to that question is covered in one of the technical points you note

Changing a variable to a property is a breaking change

If you publish any class to anyone (even your future self), you're bound to either keep to that interface or break an arbitrary amount of code that depends on it. Forever.

Encapsulation solves this issue by providing (or rather, describing) a way to be sure you can make changes to the implementation in the future without breaking any code outside the class. That is, using public fields binds you to them indefinitely, whereas auto-generated properties have the ability to change in the future without breaking calling code.

I'd like to note here that turning a field into a property is not a breaking change in all programming languages, but it is in C#.

Encapsulation

Implied in the question is another one I'd like to tackle about whether or not properties can provide encapsulation.

Wikipedia defines Encapsulation as two related but separate concepts:

  • A language mechanism for restricting access to some of the object's components.

  • A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.

The question asserts that

[properties are] fields which can be changed from any class, and that, as far as I know, violates encapsulation.

I reject this assertion based on both of Wiki's definitions. Let me give an example straw man scenario and then ask some questions about it to investigate.

I've made a class called Temperature. It has public properties for getting and setting its temperature in Celsius, Fahrenheit, and Kelvin. It will do any conversions between them simply by writing one than reading another.

Question 1: How is Temperature used?

  1. Reading and/or writing the properties directly, per the above interface description

  2. Reading and/or writing some internal state that isn't part of the public interface specified above

  3. Some other answer that I'm unaware of

Question 2: How is Temperature implemented?

  1. Each property has a backing hidden variable, with each setter updating all three backing variables. Getters just echo the variable.

  2. There is one backing variable (in Rankines) updated by all three setters. Each getter converts from Rankines to the appropriate unit on the fly.

  3. Temperature stores only a GUID. Any get/set requests are passed with the GUID to a web service, which handles the actual business of conversion.

  4. It's impossible to tell from the interface defined, but any of the above would work (modulo network exceptions).

  5. Some other answer that I'm unaware of

The answers I would pick are 1 and 4. That is, properties defined some public interface to the class, but obfuscated how the class was actually implemented. Properties satisfy "restricting access to some of the object's components" by hiding what those components even are. In conjunction with the class itself, they also help with "facilitates the bundling of data with the methods (or other functions) operating on that data" by being able to share information among themselves.

TL;DR: Properties can (and commonly are) used to support encapsulation.

Related Topic