English 中文(简体)
How do you keep your backing fields organized? (Styles/Patterns)
原标题:

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.

最佳回答

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; }
  }
}
问题回答

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;}
}

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.

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...

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.

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.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签