2

First of all, I have read the question asking for the difference between fields and properties and I know what it is used for.

Now on to my question, I wanted to create a property where I am sure that get and set will both be empty, so I do get; set;. All good and well. But now I realised that I have just made a public field with a capital name, it is in all ways identical.

Even the argument of it being used so future code does not depend on implementation cannot be said, as I can simply make this a property and implement a getter or a setter. The semantics of a field and a property are identical outside the class it is defined in.

So my question is, should I use a field or a property when a property would simply use get;set;?

So this:

public IEnumerable<string> Products;

is identical in all ways to this:

public IEnumerable<string> Products { get; set; }
Community
  • 1
  • 1
vrwim
  • 13,020
  • 13
  • 63
  • 118

3 Answers3

8

should I use a field or a property when a property would simply use get;set;?

Use a property... for the practical reasons below, and for the philosophical reasons that properties expose a state API, whereas fields expose a state implementation detail.

The semantics of a field and a property are identical outside the class it is defined in.

That's not true.

  • The difference is visible via reflection, which is often very important. For example, many binding frameworks won't use fields, only properties.
  • You can pass a mutable field by ref, but not a property - so changing a field to a property breaks source compatibility. (Code using SomeMethod(ref x.Products) will become invalid when Products becomes a property.)
  • Changing a field to a property also breaks binary compatibility, so if assembly X was built against assembly Y v1.0, and you change a field to a property for assembly Y v1.1, then you'd need to rebuild assembly X or it would fail to execute correctly
  • If you have a mutable value type (please don't do this) then writing foo.Location.X = 10 works when Location is a field (because x.Location is classified as a variable) whereas it doesn't when Location is a property (because then the expression x.Location is classified as a value). If you have a method (in your evil mutable type) which mutates the value instead, then foo.Location.DoSomething() will compile in both cases, but have a different effect. Fun for all the family.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Despite being good answer as usual most of the point are already covered in question OP linked in the post... I'm sure your answer is more convincing, but I'm not sure it will actually help OP. – Alexei Levenkov Nov 04 '15 at 08:13
  • @AlexeiLevenkov: I can't actually find the content of my bullet points in that question. Most of the answers there talk about the philosophical differences and what else you can do with a property - the latter part of which isn't relevant when the OP specifically wants a trivial property for the moment. To put it another way: if the OP really read the answers there and still asserted that a public field and a public automatically implemented property are semantically equivalent, then the ways in which that is untrue clearly didn't make it through... so stating them clearly here *should* help. – Jon Skeet Nov 04 '15 at 08:17
  • Not top rated, but they are there - binary compat - http://stackoverflow.com/a/295230/477420 (which implies reflection, but indeed that is not covered), ref - http://stackoverflow.com/a/295380/477420 (and similar http://stackoverflow.com/a/32025538/477420 which also include Interlocked remark). Reflection is not there directly. – Alexei Levenkov Nov 04 '15 at 08:26
  • @JonSkeet indeed it does, I didn't know all these things. And FYI, I always use a property when something's exposed to the outside, I just wanted more info on why that is the case – vrwim Nov 04 '15 at 08:27
  • @AlexeiLevenkov: Right, yes - I searched for "compat" to find mentions of compatibility, and didn't see anything. I still think this answer is useful to address the specific concerns of the OP. – Jon Skeet Nov 04 '15 at 08:57
  • Jon Skeet Indeed it is useful. it just *should not* helped OP :). I think you still @vrwim actually asking where is actual difference since *compiling code* against changed source still work (which is the case of most non-shared libraries and rarely concerns developers of final user facing products). – Alexei Levenkov Nov 04 '15 at 17:02
  • @AlexeiLevenkov: I'm not sure I followed that comment, but even if you're recompiling the two still aren't equivalent because of `ref` - my middle bullet. Oh, and another example I've just thought of, which I'll add now. – Jon Skeet Nov 04 '15 at 17:19
  • Structs is nice addition (can't upvote twice :) ). Trying to exand my comment: I don't think most people actually experience these incompatibilities - and hence it is much harder to think about them as possible problems. I doubt many people use structs simply because writing one that does not cause ridiculous errors is hard, same for `ref` on fields - all samples one can find use `ref` on local variables - so how one would come up with using it on field. So if you always see source code that does not use these features it is hard to reason why it could be a problem. – Alexei Levenkov Nov 04 '15 at 17:59
  • ... somewhat similar to many Eric Lippert's answers on "why C# compiler does not implement trivial thing YYY" - 99% of people never see/think beyond most basic usage of a feature and it feels obvious to implement, but there is huge set of other things that are indirectly impacted by "YYY" and only tiny portion of all developers can instantly come up with list of why implementing "YYY" is actually insanely hard. – Alexei Levenkov Nov 04 '15 at 18:03
1

Its depend on the situation. I'll prefer to use the property over the field. You have mentioned that public IEnumerable<string> Products; and public IEnumerable<string> Products { get; set; } are same, but in actual they are not. During compilation the property will get converted into two methods (i.e. get_Products() and set_Products()).

The advantage of property is to allows you to specify the custom code before assigning and returning the data, this is not possible with the field. Check the example below

public IEnumerable<string> Products
        {
            get
            {
                if(DateTime.Now.Date > Convert.ToDateTime("01-01-2016"))
                {
                    //Return future product
                    return new List<string>();
                }
                else
                {
                    // return current products
                    return new List<string>() { "testing" };
                }
            }
            set
            {
                if (DateTime.Now.Date > Convert.ToDateTime("01-01-2016"))
                {
                    //ignore assign product
                    Products = new List<string>();
                }
                else
                {
                    // add assign product
                    Products = value;
                }
            }
        }
Avinash Jain
  • 7,200
  • 2
  • 26
  • 40
0

Using the auto-property syntax is preferable because it creates a read/write property with a private backing field, thus allowing you to change the implementation (from a private scalar field to a dictionary entry or another backend with some other custom logic), thus freeing the "class's interface" (not the same thing as an interface) from its implementation.

Note that for collection member properties, it is advisable to make their setters private, like so:

public IEnumerable<String> Products { get; private set;}

...that way only the containing class can alter it.

Another alternative is the private readonly field, in C# 6 you can use auto-implemented properties with readonly backing fields like so:

public IEnumerable<String> Products { get; } = SomeSource.GetProducts();
Dai
  • 141,631
  • 28
  • 261
  • 374
  • Is `public IEnumerable Products { get; } = SomeSource.GetProducts();` identical to `public IEnumerable Products { get { return SomeSource.GetProducts(); } }`? – vrwim Nov 04 '15 at 08:14
  • @vrwim No, in the first example the initializer is only called once and becomes the value of the hidden `private readonly` field. In the second example, the `GetProducts` call is made every time the property is accessed, there is no hidden private field backing store. – Dai Nov 04 '15 at 08:32