Difference between assigning to auto-Implemented properties VS their backing fields within the class

efficiencynetprogramming practicespropertiesvb.net

Before I started using auto-implemented properties, I was taught that when assigning properties in the constructor (because of the potential of making a property read only), I should assign directly to the private member for the property (which we would usually name with the property's name with an underscore in front of it. EX: _propertyName.)

When I switched to using auto-implemented properties, I kept the practice, even so much as establishing that only the private members should be referenced inside the property's class. I understand those auto-implemented, private members are referred to as "Backing Fields".

Considering the usefulness of backing fields, I find it fascinating that they are invisible to intellisense until fully typed. Furthermore, I made the observation that when you auto-implement the property, it appears as though you can assign to a Read Only property within the property's class.

Considering the changes that have happened in the .net framework, I am beginning to question what is the "Right" way to handle properties from within the class. I understand that is somewhat subjective, but I wonder, are there drawbacks to the way I have done this? So I'm left with a few questions on how this works, and what the implications on my software's design (however minor) are:

  1. Does calling the auto-implemented property from within property's class call the Get and Set (even when set to "read only")?
  2. Does calling the property's backing field bypass this?
  3. Am I wasting (however few) processor cycles by using the the property instead of the backing field?
  4. Or am I exposing myself to a potential problem in the future by using the backing fields?

Or broader question:

What is difference between assigning to auto-Implemented properties VS assigning directly to their backing fields?

UPDATE

I now understand my question is more applicable to vb.net, as you cannot access auto-implemented Backing Fields in C#. And if you wanted to assign directly to a backing field in C#, you cannot use the auto-implement.

So the broader question and the question of practice is still applicable to either language.

UPDATE TO TRY SCARE UP A NARROWED ANSWER FOR VB

So I've gotten a lot of helpful feedback, but in all the answers none have directly addressed all 4 specific questions (perhaps because they initially seem irrelevant) but in my situation, I'm assigning to the backing fields of Auto-Implemented properties. This means that it does not bypass any critical, breaking code (as the auto-implemented, hidden Get and Set have no logic in them).

Bearing in mind that backing fields are Private and that you would only be able to assign to the backing field of a property that you personally wrote as auto-implemented (as you wrote the class), here's another way to sum up some of my questions above:

What is the issue with directly assigning to the backing field of an auto-implemented property?

Thanks!

Best Answer

If you assign directly to a backing field, you can be certain it will work.

If you assign using the property that wraps the backing field, you can't be sure it will work. If the property is overridden in a derived class, that version of the property will be called instead. And since the constructor of the base class is called before the constructor for the derived class, you'll be calling a property on a class that is not fully initialized, and it could result in an error.

Here is an example that produces such an error:

class Base
{
    public virtual string Foo { get; set; }

    public Base()
    {
        Foo = "Hello world!";
    }
}


class Derived : Base
{
    List<string> _history;

    public Derived() : base()
    {
        _history = new List<string>();
    }
    public override string Foo
    {
        get
        {
            return base.Foo;
        }
        set
        {
            _history.Add(value);
            base.Foo = value;
        }
    }
}

If you instantiate a Derived, it'll raise a null reference exception because the history list is not yet initialized. This would not occur if you assigned to the backing field directly.

See my example on DotNetFiddle