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 _myBackingFie开发者_如何学编程ld = "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.
精彩评论