1

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!

  • What do you mean by assigning to auto implemented property backing field? That should not be possible. – Esben Skov Pedersen Mar 7 at 20:54
  • @EsbenSkovPedersen Ah, I now understand that you cannot assign to auto implemented properties in C#, so that part of the question is only applicable to vb.net. I've updated the question. – Hawkeye Mar 7 at 22:41
4

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

  • 1
    Pretty easy error to spot, though. – Robert Harvey Feb 26 at 3:30
  • Oh, that's I scenario I didn't think of. It's a wonder why Microsoft doesn't encourage using the backing fields within the class through intellisense or some warning, which takes me back to one of my points in my question: does calling the auto-implemented property from within property's class call the Get and Set? Normally I would test this debugging, but there is no visible code to step through with the auto-implemented properties. Thanks for the input. You've convinced my to keep my code as-is. Would you happen to be able to address the 4 points I listed? – Hawkeye Feb 26 at 20:04
  • 1
    @RobertHarvey: Pretty easy to spot in a controlled environment, yes. But it's still a runtime error, which is something I'd suggest avoiding like the plague where possible. In sufficiently complex applications where logging leaves much to be desired, there is no adequate mocking for local debugging, or spotty exception handling is implemented (let's be real here, we've all seen these projects), runtime exception can become exceedingly annoying to debug. – Flater Feb 27 at 22:00
  • 1
    To the person writing the base class, the problem may actually be impossible to spot, unless they have the option to make the class sealed or make the property non-virtual or private. Because the offending code would not have been written yet. – John Wu Feb 28 at 1:20
  • @Hawkeye you can debug auto properties by placing a breakpoint on the setter(Place cursor on setter and press f9) – Esben Skov Pedersen Mar 7 at 20:44
1

Design answer:

You can think of assignment as an function call that has side effects. When you assign to backing fields it means that there are no preconditions and no postconditions. Responsibility of setting correct value is given to every code piece that sets the value. Even if those pieces of code are in one class.

If requirements for that backing field will change you will have to change every place where that field it set. This is obviously not good and should be avoided. Therefore you should use auto-Implemented properties whenever possible.

Author of "Practical Object-Oriented Design in Ruby":

"Always wrap instance variables in accessor methods instead of directly referring to variables..."

"Hide the variables, even from the class that defines them, by wrapping them in methods..."

  • Interesting. I wondered if there was a strict view on this. It sounds like good academic theory, but can you think a particular example of how assigning to the Backing Field would be a problem, besides causing more work when requirements change? – Hawkeye Mar 7 at 20:26
  • Auto-implemented properties trade complexity for flexibility. I don't think that you can get into trouble if you use less complex structures. Actually if requirements would not change (usually not realistic) it would make more sense to not use them at all for the sake of development speed. – Žilvinas Rudžionis Mar 11 at 22:02
1

You should always use the getter/setter as that is the only way to guarantee consistent results.

It’s possibly a minor performance hit, that would depend upon the jitter — it is free to look into the call and inline it.

If you sometimes call the property and sometimes set the backing variable directly, you are opening yourself up to missing a breaking change.

Consider, you have a C# property with a backing field, and decide to make it an auto-prop, but don’t remove the backing field. Ideally this should be perfectly safe, but if the backing field was used outside of the property, it’s broken.

In VB, you have the opposite problem, if you take an auto-property and add logic, reference to the backing field then bypasses that logic.

Ignoring the extremely unlikely scenario of it being a performance bottleneck (not meeting specs trumps everything)...

You should be using the backing field when you have logic and need a way to bypass it in certain circumstances. You should also use it when you want a property to be read only externally, but writeable internally (vb doesn’t have private setters for auto properties).

  • I see what you're saying. So it is your understanding then that Auto-Implemented properties do not call the hidden Get and Set when the backing field is called? I've gotten a lot of very informative responses, but something that I have not heard addressed is: is there any reason that I should not use the backing fields for auto-implemented properties? Taking into consideration all the responses I've gotten so far, I don't see there being any risk (as there is no logic in the auto implemented Get and Set) only perhaps the benefit of less processor cycles. – Hawkeye Aug 29 at 18:15
  • 1
    First off, yes, using the backing field bypasses the hidden Get/Set.Secondly, the auto-prop backing field is accessible (in VB.Net), and unlike in C#, the name is guessable because it uses the same convention as is recommended for non-auto properties. Which means that if you add logic, you will probably break things. Now, if you never add logic or rename the property and you have option explicit on, the only harm will be that it is harder to reason about your program – jmoreno Aug 29 at 21:22
  • I see. The possibility of reworking classes is a good case to not use the backing fields, but then again John Wu's answer makes a good case for where you need to assign to the backing field, but I guess in his case, you would not use auto implemented properties. I'm getting the picture that this is something that Microsoft might need to handle differently in IntilliSense. Thanks for your input! – Hawkeye Aug 30 at 22:41
  • @Hawkeye: John Wu’s answer actually shows the benefit of using the property — it crashes. If you use the property it crashes and you get a bug filed and you fix it. If you use the backing field it always works, but it never does what you want it to. That’s a problem. – jmoreno Aug 31 at 0:21
  • I'm sure what you are saying is correct for some implementations, but certainly not it all instances. Similar to John Wu's answer, if I needed a property that happens to come from the base class, but needs to be a calculated value (instead of a static value as in John Wu's example) then I would need to assign to the backing-field (and not use an auto implemented property.) I'm not yet sure any hard and fast rules should be made on the matter. And I don't think John Wu's answer is taking everything into account either. That's why I haven't accepted any answers yet. – Hawkeye Sep 3 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.