views:

7124

answers:

3

I'm used to writing classes like this:

public class foo {
  private string mBar = "bar";
  public string Bar {
    get { return mBar; }
    set { mBar = value; }
  }
  //... other methods, no constructor ...
}

Converting Bar to an auto-property seems convenient and concise, but how can I retain the initialization without adding a constructor and putting the initialization in there?

public class foo2theRevengeOfFoo {
  //private string mBar = "bar";
  public string Bar { get; set; }
  //... other methods, no constructor ...
  //behavior has changed.
}

You could see that adding a constructor isn't inline with the effort savings I'm supposed to be getting from auto-properties.

Something like this would make more sense to me:

public string Bar { get; set; } = "bar";
+2  A: 

In the default constructor (and any non-default ones if you have any too of course):

public foo() {
    Bar = "bar";
}

This is no less performant that your original code I believe, since this is what happens behind the scenes anyway.

Matthew Scharley
It's more work if you have multiple disparate constructors, compared to just initializing the underlying field and not using an automatic property - I don't really see what gain you get from the auto-property in that scenario...
Bittercoder
There is a difference, though: Initializing it right away means it's initialized even before the default constructor. I recently had an application where this actually mattered for some strange reason I don't understand.
Michael Barth
+15  A: 

You can do it 2 ways, either via the constructor of your class:

public class foo {
  public foo(){
    Bar = "bar";
  }
  public string Bar {get;set;}
}

Or you can use the DefaultValue attribute (http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx):

public class foo {
  [DefaultValue("bar")]
  public string Bar {get;set;}
}

I much prefer the first option as DefaultValueAttribute requires reflection to get the value (or at least, so I've found).

If you've got another constructor (ie, one that takes paramters) or a bunch of constructors you can always have this:

public class foo {
  private foo(){
    Bar = "bar";
  }
  public foo(int something) : this(){
    //do normal constructor stuff
  }
  public string Bar {get;set;}
}

If you always call the "default" constructor you can have all initalisers set up in that nicely and you're acutal constructors as you want

Slace
Hmm I guess I really showed 3 ways didn't I... :P
Slace
the last example is a bit misleading in that inline initialization results in the variables being initialized before other constructor logic. Your pattern results in the initialization happening after normal constructor logic (at least in example 3, for the int something constructor).
spoon16
I was working off the presumption that Bar was only to be initialised not utilised by the constructor, so its point of initialisation is irrelivant in the overall construction process
Slace
Personally, I find myself using it the other way normally, ie. the generic one calls the specialised one with some default parameters and does nothing itself. In this case, order of calling isn't really important.
Matthew Scharley
DefaultValueAttribute does NOT set the value of a property. All it does is tell Visual Studio what the default value should be, so that in the Property Window, the will be bolded if it is not set to that value. It does not change the value in any way.
James Curran
Correct James, but you could conciveably use reflection to read back the default property. It wouldn't be all that pretty but it'd be do-able
Slace
+1 James >> MSDN: "A DefaultValueAttribute will not cause a member to be automatically initialized with the attribute's value. You must set the initial value in your code."
Even Mien
Minor correction to the example; to call a constructor from the same class use: "this()" rather than "<class name>()" as shown. Helpful answer nonetheless.
mrjoltcola
+9  A: 

It's unfortunate that there's no way of doing this right now. You have to set the value in the constructor. (Using constructor chaining can help to avoid duplication.)

Automatically implemented properties are handy right now, but could certainly be nicer. I don't find myself wanting this sort of initialization as often as a read-only automatically implemented property which could only be set in the constructor and would be backed by a read-only field. It's possible that both of these will be fixed in C# 5, which I strongly hope will address immutability concerns. (I don't think either of them are scheduled for C# 4.)

Jon Skeet