5

is there any effective difference between Foo.Something and Bar.Something in this example?

class Foo
{
    public string Something;
}

class Bar
{
    public string Something{get; set;}
}

class Program
{
    static void Main(string[] args)
    {
        var MyFoo = new Foo();
        MyFoo.Something = "Hello: foo";
        System.Console.WriteLine(MyFoo.Something);

        var MyBar = new Bar();
        MyBar.Something = "Hello: bar";
        System.Console.WriteLine(MyBar.Something);
        System.Console.ReadLine();
    }
}

AFAIK they behave exactly the same. If they do why not to use plain Fields like in Foo? In java we use setters to be able enforce new invariants without breaking code and getters to return safe data but in c# you can always rewrite Foo into this:

class Foo
{
    private string _Something;
    public string Something
    {
        get { 
            //logic
            return _Something; 
            }
        set { 
            //check new invariant
            _Something = value; 
            }
    }
}

And old code will not be broken.

adekcz
  • 308
  • 2
  • 12

5 Answers5

11

AFAIK they behave exactly the same.

No they don't.

  • Fields can't be used in data binding (at least in some binding implementations)
  • You can add more logic later for properties without breaking source or binary compatibility
  • Properties can't be passed by reference
  • You can't add an initializer to an automatically implemented property
  • They'll clearly be different in terms of reflection
  • Philosophically, properties are logically part of the API whereas fields are an implementation detail

in c# you can always rewrite Foo into this: [...]

Well you can if you don't care about binary or source compatibility, yes. In some cases that's really not an issue - in other cases it's very, very much an issue. Why not make the choice to expose your API rather than your implementation details from the start? It's not like adding { get; set; } in your code is adding much clutter...

For more ranting, see my article on this.

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • 1
    And auto-properties can't have (the equivalent of) field initializers. For example if you want `Something = "initial"` initially, with the property you will have to make your instance constructor explicit and write the assignment in the body of that constructor (or all constructors unless they "chain" each other with the `: this(...)` syntax). – Jeppe Stig Nielsen Mar 21 '13 at 15:15
  • Jon Skeet walks into a question, 4 upvotes. – EaterOfCode Mar 21 '13 at 15:16
  • @JeppeStigNielsen: True, true. – Jon Skeet Mar 21 '13 at 15:17
  • 1
    @EaterOfCorpses Which is largely irrelevant to him, as he's already well past the rep cap for the day anyway. – Servy Mar 21 '13 at 15:28
1

Foo.Something is a field, Bar.Something is an automatically implemented property. That's a huge difference.

You can just access properties the same way as fields, but internally a set/get method is called when you access a property.

So when you say myBar.Something = "asdf", the C# compiler translates this to a call to a setter method: myBar.set_Something("asdf"). The setter and getter methods are generated automatically for you, as well as a backing field for the actual value.

By changing Foo.Something to a property with get and set methods, you are breaking binary compatibility, that means you'll have to recompile all assemblies that used Foo.Something when it still was a field.

Botz3000
  • 37,236
  • 8
  • 100
  • 125
0

The getters and setters of a property (including automatic ones) have a method call cost. Public fields should be avoided in order to keep things clean with access.

Daniel A. White
  • 174,715
  • 42
  • 343
  • 413
  • You: _Public fields should be avoided_ I guess public **`readonly`** fields are alright? The BCL uses them. Of course this is not relevant to the original question. – Jeppe Stig Nielsen Mar 21 '13 at 15:07
  • @JeppeStigNielsen i guess so. – Daniel A. White Mar 21 '13 at 15:08
  • 1
    @JeppeStigNielsen: The BCL rarely uses readonly *instance* fields. Constants (even non-const constants, if you see what I mean) are a different matter. – Jon Skeet Mar 21 '13 at 15:18
  • @JonSkeet I guess you're right. For example `KeyValuePair` doesn't use `readonly` instance fields, it uses `get`-only instance properties (no `private` setters found by reflection, though). – Jeppe Stig Nielsen Mar 21 '13 at 15:31
0

1) You can add private accessor to get or set and control access to property.

public object MyProp {get; private set;}

You can read prop everywhere, but write only inside class

2) You can connect some logic to read/write property. In case of field you can not do anything additional

3) You can not serialize fields

Jacek
  • 10,507
  • 21
  • 58
  • 108
0

public string Something{get; set;} is just syntactic sugar; the compiler actually expands this to methods. So there is little point in having all get; set; fields all over the place, just for the sake of it.

David S.
  • 5,523
  • 1
  • 34
  • 68