views:

1956

answers:

15

I see a lot of example code for C# classes that does this:

public class Point {
    public int x { get; set; }
    public int y { get; set; }
}

Or, in older code, the same with an explicit private backing value and without the new auto-implemented properties:

public class Point {
    private int _x;
    private int _y;

    public int x {
        get { return _x; }
        set { _x = value; }
    }

    public int y {
        get { return _y; }
        set { _y = value; }
    }
}

My question is why. Is there any functional difference between doing the above and just making these members public fields, like below?

public class Point {
    public int x;
    public int y;
}

To be clear, I understand the value of getters and setters when you need to do some translation of the underlying data. But in cases where you're just passing the values through, it seems needlessly verbose.

+5  A: 

It encapsulates setting and accessing of those members. If some time from now a developer for the code needs to change logic when a member is accessed or set it can be done without changing the contract of the class.

Joseph Daigle
Typo "had" for "add".
Steve Jessop
A: 

You never know if you might not need some translation of the data later. You are prepared for that if you hide away your members. Users of your class wont notice if you add the translation since the interface remains the same.

EricSchaefer
A: 

The biggest difrence is that, if ever you change your internal structure, you can still maintain the getters and setters as is, changing their internal logic without hurting the users of your API.

gizmo
+4  A: 

It's also much simpler to change it to this later:

public int x { get; private set; }
Brad Wilson
I... didn't even know you could do that.
Merus
@Merus only in C# 3.0
Will Eddins
+16  A: 

I tend to agree (that it seems needlessly verbose), although this has been an issue our team hasn't yet resolved and so our coding standards still insist on verbose properties for all classes.

Jeff Atwood dealt with this a few years ago. The most important point he retrospectively noted is that changing from a field to a property is a breaking change in your code; anything that consumes it must be recompiled to work with the new class interface, so if anything outside of your control is consuming your class you might have problems.

Dexter
Thanks for that link and convincing me that things will actually break in the field/property switchover. It's strange to me, since the syntax is the same regardless.
tclem
You'd think it would compile down to the same thing, but obviously the internal mechanics are slightly different.
Dexter
In C#, a property with a get and set compiles to a pair of methods like get_PropertyName() and set_PropertyName(type value). The property syntax in C# is just syntactic sugar. Properties can execute code, so it would not make sense for them to compile down to the same code as a field.
Jason Jackson
The JIT compilers does optimize a property with no code to be equivalent to a field, so there is no reason to not use properties given the shorthand syntax in C# 3.0+
Erv Walter
A: 

If you have to change how you get x and y in this case, you could just add the properties later. This is what I find most confusing. If you use public member variables, you can easily change that to a property later on, and use private variables called _x and _y if you need to store the value internally.

Kibbee
+1  A: 

The idea is that even if the underlying data structure needs to change, the public interface to the class won't have to be changed.

C# can treat properties and variables differently at times. For example, you can't pass properties as ref or out parameters. So if you need to change the data structure for some reason and you were using public variables and now you need to use properties, your interface will have to change and now code that accesses property x may not longer compile like it did when it was variable x:

Point pt = new Point();
if(Int32.TryParse(userInput, out pt.x))
{
     Console.WriteLine("x = {0}", pt.x);
     Console.WriteLine("x must be a public variable! Otherwise, this won't compile.");
}

Using properties from the start avoids this, and you can feel free to tweak the underlying implementation as much as you need to without breaking client code.

Rob Pilkington
+1  A: 

AFAIK the generated CIL interface is different. If you change a public member to a property you are changing it's public interface and need to rebuild every file that uses that class. This is not necessary if you only change the implementation of the getters and setters.

+1  A: 

Also to be considered is the effect of the change to public members when it comes to binding and serialization. Both of these often rely on public properties to retrieve and set values.

TheZenker
+1  A: 

Maybe just making fields public you could leads you to a more Anemic Domain Model.

Kind Regards

marcospereira
A: 

Setters and getters are bad in principle (they are a bad OO smell--I'll stop short of saying they are an anti-pattern because they really are necessary sometimes).

No, there is technically no difference and when I really want to share access to an object these days, I occasionally make it public final instead of adding a getter.

The way setters and getters were "Sold" is that you might need to know that someone is getting a value or changing one--which only makes sense with primitives.

Property bag objects like DAOs, DTOs and display objects are excluded from this rule because these aren't objects in a real "OO Design" meaning of the word Object. (You don't think of "Passing Messages" to a DAO, It's simply a pile of attribute/value pairs).

Bill K
A: 

Setter and Getter enables you to add additional abstraction layer and in pure OOP you should always access the objects via the interface they are providing to the outside world ...

Consider this code, which will save you in asp.net and which it would not be possible without the level of abstraction provided by the setters and getters:

class SomeControl
{

private string _SomeProperty  ;
public string SomeProperty 
{
  if ( _SomeProperty == null ) 
   return (string)Session [ "SomeProperty" ] ;
 else 
   return _SomeProperty ; 
}
}
YordanGeorgiev
A: 

Since auto implemented getters takes the same name for the property and the actual private storage variables. How can you change it in the future? I think the point being said is that use the auto implemented instead of field so that you can change it in the future if in case you need to add logic to getter and setter.

For example:

public string x { get; set; }

and for example you already use the x a lot of times and you do not want to break your code.

How do you change the auto getter setter... for example for setter you only allow setting a valid telephone number format... how do you change the code so that only the class is to be change?

My idea is add a new private variable and add the same x getter and setter.

private string _x;

public string x { 
    get {return x}; 
    set {
        if (Datetime.TryParse(value)) {
            _x = value;
        }
    }; 
}

Is this what you mean by making it flexible?

Nassign
A: 

Also, you can put breakpoints on getters and setters, but you can't on fields.

NotDan
A: 

It is also worth noting that you can't make Auto Properties Readonly and you cannot initialise them inline. Both of these are things I would like to see in a future release of .NET, but I believe you can do neither in .NET 4.0.

The only times I use a backing field with properties these days is when my class implements INotifyPropertyChanged and I need to fire the OnPropertyChanged event when a property is changed.

Also in these situations I set the backing fields directly when values are passed in from a constructor (no need to try and fire the OnPropertyChangedEvent (which would be NULL at this time anyway), anywhere else I use the property itself.

MrLane
That is not entirely true, you can have auto implemented properties read only (or write only), if you have SomePropName {get; private set;}, and then set property using the object initializers..
jhexp