42

When setting a value to a variable inside of a class most of the time we are presented with two options:

private string myValue;
public string MyValue
{
   get { return myValue; }
   set { myValue = value; }
}

Is there a convention that determines how we should assign values to variables inside of our classes? For example if I have a method inside the same class should I assign it using the property or using the private variable. I've seen it done both ways, so I was wondering if this is a choice or performance is a factor (minor, probably).

8 Answers 8

24

I would take it a step further, and bring it to 3 cases. Although there are variations on each, this is the rules I use the majority of the time when C# programming.

In case 2&3, always go to the Property Accessor (not the field variable). And in case 1, you are saved from even having to make this choice.

1.) Immutable property (passed in to constructor, or created at construction time). In this case, I use a field variable, with a read-only property. I choose this over a private setter, since a private setter does not guarantee immutability.

public class Abc
{ 
  private readonly int foo;

  public Abc(int fooToUse){
    foo = fooToUse;
  }

  public int Foo { get{ return foo; } }
}

2.) POCO variable. A simple variable that can get/set at any public/private scope. In this case I would just use an automatic property.

public class Abc
{ 
  public int Foo {get; set;}
}

3.) ViewModel binding properties. For classes that support INotifyPropertyChanged, I think you need a private, backing field variable.

public class Abc : INotifyPropertyChanged
{
  private int foo;

  public int Foo
  {
    get { return foo; }
    set { foo = value;  OnPropertyChanged("foo"); }
  }
}
8
  • 2
    +1 for MVVM example. Actually that's what sparked the question in the first place.
    – Edward
    Feb 2, 2012 at 18:38
  • 4
    +1: Mix 2/3 with AOP and you have a wonderful way of using INPC. [Notifies]public int Foo { get; set; } Feb 2, 2012 at 20:13
  • 1
    @Job To any class accessing the class, a private setter is sufficient for immutability. However, inside the class, the private setter does not prevent repeated settings of the value, following initial construction. A language feature like a 'private readonly set' might conceptually work around this problem, but it does not exist. Feb 6, 2012 at 20:16
  • 1
    I'm new to C#, so tell me, why use public int Foo {get; set;} instead of public int Foo?
    – user1827
    Feb 27, 2012 at 17:46
  • 1
    If a class or struct is going to behave as a POCO or PODS, what real advantage is there to wrapping fields in properties? I fully understand that wrapping fields in properties is useful when a class or struct needs, or might in future need, to maintain invariants with respect to its contents (perhaps by ensuring other objects are updated to match them), but if a class or struct specifies that consumers may write any values in any order without restriction or side-effects, what useful behaviors could possibly be added to a member accessor?
    – supercat
    Aug 16, 2012 at 20:11
18

Generally, I would say assign to the field in the constructor and use the property everywhere else. This way, if someone adds functionality to the property, you won't miss it anywhere.

It certainly isn't a performance factor. The optimiser will inline a simple get or set for you and the final MSIL code will probably be identical.

4
  • Any particular reason for using the field in the constructor? Less chance of strange side effects?
    – Sign
    Feb 2, 2012 at 19:15
  • 4
    @Sign: My guess is that if there is validation on the property (now or in the future), you don't want to run the risk of validation failing during construction. Validation isn't logical at this stage because the object can't be guaranteed to be stable until the constructor finishes. Feb 2, 2012 at 20:10
  • @Sign: Both what you said and what Snorfus said. Or if I want to log changes to a property, I likely don't want to log the initial setting. But, I did say "generally".
    – pdr
    Feb 2, 2012 at 20:48
  • 3
    @Sign: the problem is: if the set method of the property can be overridden in a subclass you can have a side effect during the creation of the object or an inconsistent object (i.e: the overridden property is programmed to not set any value for that field). Using properties in constructors is only safe if the set method is private or if the class is sealed.
    – Diego
    Feb 3, 2012 at 1:33
4

Depends.

First you should prefer automatic properties when possible:

public string MyValue {get;set;}

Second the better approach would probably be to use the properties, if you have any logic there you should probably be passing through it yourself, especially if that logic is thread synchronization.

But you should also take into account that it might hamper your performance (a little bit), if you are synchronizing incorrectly you can deadlock yourself, and sometime the correct path is to go around the logic in the property.

1
  • 3
    I also like public string MyValue {get; private set;}.
    – Job
    Feb 3, 2012 at 23:43
3

Well, the straight-to-the-point approach would be to just assign it to the variable itself, since you're inside a class' method and you control the class' behaviour, anyway.

But the whole point about properties is that they abstract the variable away. Whereas such a simple property as in your example has completely no use over just a simple public member variable, properties usually do (or should do) additional things inside their getters and setters. And if you want these things done automatically when changing the property inside the class, then it is of course cleaner to work on the property instead of the variable to not have to change each variable assignment when the property setting behaviour changes.

You just have to reason about it conceptually. The property is actually a handle to access some internal state of the object, which may be comprised of more than one member variable. So you have to ask yourself if you want to change the underlying internal state only (or only part of it) or the abstract property representing this state at a whole, and most times it's indeed the latter since you usually want your object to always have a consistent state.

2

If there is any chance that those property get/set implementation will change sometimes later (for example, you want to rise an event when calling set, or you will add some lazy evaluation mechanism later to your get function), then it may be a good idea that your code inside the class will use the property in almost all cases except for the - most probably rare - cases where you explicitly don't want those event or lazy evaluation mechanisms to be used.

Anyhow, whatever you will do, there is a good chance that when you change the property implementation later in such a way, you will have to look at all places inside your class accessing those property to check if really the property shall be accessed or the private variable shall be used.

2

I always use the public property.

Often some logic which should always run when the property is set is added to the set method of a property, and setting the private field instead the public setter will bypasses any logic there.

You have a comment about MVVM leading to this question, and I feel this is even more important when working with MVVM. Many objects raise a PropertyChange notification the setter, and other objects can subscribe to this event to execute some action when specific properties change. If you set the private variable, these actions will never execute unless you also manually raise the PropertyChanged event.

1
  • +1 Yes in most cases (MVVM) the PropertyChanged event is a must. And that can only get fired inside a property. Good explanation.
    – Edward
    Feb 2, 2012 at 18:59
1

Generally, it's up to you what you should do with a property and its backing field when getting/setting.

Most often, just to be consistent across code, you should use public accessors wherever they are available and appropriate. That allows you to refactor with minimal code change; if the method doing this setting needs to be stripped out of the class and put somewhere else where the backing field is no longer available (like a base class), who cares? You're using something that's available wherever the class itself is to do the job. The backing field, in most cases, is an implementation detail; nobody outside your class should know it exists.

The main situation I can think of when you should use the backing field and NOT the property accessor is when the accessor has additional logic (validation, or updating other state information in the class) which you don't want to run. Initial population of an object is an example; you may have a class that uses two property values to calculate a third, which is also stored in a backing field (for persistence reasons). When initializing a new copy of that object given data from the DB, the property accessors which each recalculate the third value may complain if the other needed value is not set. By using the backing fields to set the initial values of these two (or three) properties, you bypass the validation/calculation logic until the instance is in a consistent enough state for the logic to work normally.

0

Always use the one that makes sense. Yes, I know that sounds pretty bogus to the point of being a non-answer.

The point of properties is to provide an interface through which you can safely access a data model. For most situations you always want to safely access the data model through that interface, such as:

public Foo Bar
{
  get { return _bar; }
  set { _bar = doSomethingTo(value); }
}

But in other situations, you may simply be using a property as a view of a data model:

public Double SomeAngleDegrees
{
  get { return SomeAngleRadians * 180 / PI; }
  set { SomeAngleRadians = value * PI / 180; }
}

If it makes sense to use the radians form of SomeAngle, then by all means use it.

In the end, be sure to drink your own kool-aid. Your public-facing api should be resilient enough to work internally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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