views:

104

answers:

6

c# 3.0 offers us getters and setters with compiler generated backing fields - this is really great, but there are plenty of times that you still need to use a backing field.

In a perfect world (opinion), you would be able to do something like

class MyClass {
  ... stuff ... 

  public string MyProperty {
    private string _myBackingField = "Foo";

    get { return _myBackingField; }
    set { _myBackingField = value; }
  }
}

instead of

class MyClass {
  private string _myBackingField = "Foo";

  ... stuff ...

  public string MyProperty {       
    get { return _myBackingField; }    
    set { _myBackingField = value; }
  }
}

Does anyone have suggestions or techniques which come close to this? Or to put it another way - what is the clearest way to keep your backing fields and properties organized.

+5  A: 

I tend to keep the backing fields together at the top, but then I do that with method variables too. Perhaps its a carry over from some of the older languages where variable declaration was always the first step, but it just seems more organized to me than declaring variables inline as needed.

If you don't like declaring variables at the top, the closest I've seen to your "ideal" style would be:

private int _integer1 = 0;
public int Integer1 
{
    get {return _integer1;}
    set {_integer1 = value;}
}
Chris
This is exactly what I do when I can't use autoimplemented properties.
Konamiman
Ditto, same for me
gmagana
-1 for keeping variable declaration on top of each method.
Alex Bagnolini
@Alex because my personal preference is so abhorrent as to deserve your explicit disapproval, and I care greatly about such too! :/
Chris
+4  A: 

I still prefer

class MyClass {
  private string _myBackingField = "Foo";
  private string _myOtherBackingField = "bar";

  ... stuff ...

  public string MyProperty {       
    get { return _myBackingField; }    
    set { _myBackingField = value; }
  }
  public string MyOtherProperty {       
    get { return _myOtherBackingField; }    
    set { _myOtherBackingField = value; }
  }
}

If the lack of proximity bothers you, you can put the backing field for each property above the property it services.

class MyClass {

  private string _myBackingField = "Foo";
  public string MyProperty {       
    get { return _myBackingField; }    
    set { _myBackingField = value; }
  }
  private string _myOtherBackingField = "bar";
  public string MyOtherProperty {       
    get { return _myOtherBackingField; }    
    set { _myOtherBackingField = value; }
  }
}
Robert Harvey
+1  A: 

Why would you put "...stuff..." between the property and the field? I'm a firm believer in keeping tightly-coupled things as close as possible:

class MyClass {
   ... stuff ...

  private string _myBackingField = "Foo";
  public string MyProperty {       
    get { return _myBackingField; }    
    set { _myBackingField = value; }
  }
}

I would also not introduce an extra field unless I had to:

  • because I need logic the in accessors
  • for (BinaryFormatter) serialization reasons

In the example given, I'd just use an auto prop:

class MyClass {
   ... stuff ...
  public MyClass() {
      MyProperty = "Foo";
  }
  [DefaultValue("Foo")]
  public string MyProperty { get;set; }
}

Obviously, some kind of auto-prop syntax that allowed a default would be nice here, but I don't need it, so I don't expect it any time soon. It doesn't solve a big enough problem to be worth much effort...

Marc Gravell
And assign it in the constructor, right?
Alex Bagnolini
How much of a performance hit do I take by using the attribute for setting the default value, rather than just setting a backing field directly in code?
Robert Harvey
Robert, You have to set the backing field directly in code. From 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." http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx
s_hewitt
Sorry, I didn't mean to cause confusion; the **constructor** is the code that sets the field. The `[DefaultValue]` is just my force-of-habit, in self-documenting the default.
Marc Gravell
+1  A: 

I agree that the OP's "perfect world" example would be useful. An auto-property wouldn't work for a lazy-loading scenario:

class MyClass 
{  
    ... stuff ...   
    public string MyProperty 
    {    
        private string _myBackingField;    
        get 
        { 
            if (_myBackingField == null)
            {
                myBackingField = ... load field ...;
            }
            return _myBackingField; 
        }    
        set { _myBackingField = value; }  
    }
}

In fact I raised this as a suggestion on Microsoft Connect some time ago.

Joe
lazy loading was actually the use case that inspired this question.
sylvanaar
A: 

In practice, it doesn't seem to matter.

In my experience, once a class passes a certain threshold of complexity (which is basically the threshold between "trivial" and "non-trivial"), I no longer navigate through the class by scrolling around in its source, I navigate by using Go To Definition and Find Usages.

Using linear proximity to imply things about relationships between class members seems like a good idea, but I think it really isn't. If I see this:

private string _Foo;
public string Foo 
{
    // arbitrarily complex get/set logic
}

the implication is clear: _Foo is used only by the Foo property. That implication's not dependable, though. The only way for me to be certain that there's no code in the class that's manipulating _Foo is to inspect it. Well, if I can't rely on proximity to tell me anything, why should I care about proximity at all?

These days, I just alphabetize my class members from the start. This frees me up from having to think about something (where should I put this member, and why should I choose that place for it?) that doesn't really matter.

Robert Rossney
A: 

What I prefer:

public int Integer1 
{
    get {return _integer1;}
    set {_integer1 = value;}
}
private int _integer1 = 0;

Why?

  • because the property is much more important than the backing field so it should be read as the first.
  • if you comment your property, what reads nicer?

this

private int _integer1 = 0;
///<summary>
/// this is my property, enjoy it
///</summary>
public int Integer1 
{
    get {return _integer1;}
    set {_integer1 = value;}
}

or

///<summary>
/// this is my property, enjoy it
///</summary>
public int Integer1 
{
    get {return _integer1;}
    set {_integer1 = value;}
}
private int _integer1 = 0;

The approchach with the backing field at the end is much more readable imho. The same holds for applying attributes to the property.

stej