C# 1.0 was designed 20 years ago with a new feature never before seen in any language: “properties”, which act internally like methods (they contain code) but externally like fields (you access them without trailing parentheses and they don’t take arguments like methods do). It was a novel concept making encapsulation more intuitive, but now I wonder if properties have come so far that they’ve completely obviated the need for fields?
I mean, we have “auto properties” which are basically fields and properties wrapped up all into one, making it really easy to support things like serialization and data binding that might depend on properties being present, without a lot of boilerplate:
And self-initializing readonly properties:
And expression bodied properties:
So properties are extremely versatile now and can be used in all sorts of scenarios. This leads to the question: what’s the point of fields anymore? Anything a field can do, a property can also do. We can’t really get rid of fields, since all sorts of existing code uses them, but maybe they can be rewritten in the back end to reuse the property code, just with some sort of flag that marks them as special so that legacy serializers and data binding libraries can tell the difference as needed? And then they can be deprecated, so folks know that they’re not needed anymore and you can just use properties instead.
Or am I missing something important about fields that distinguishes them from properties? Am I completely crazy? 🙂
Properties predate C#. They were present in COM least.
Properties are just syntax sugar around fields. And people don’t use them for private state. No reason to use a property for that.
Properties are sugar. Remember this. They are just two methods with the names get_ and set_. Where would the state actual be stored if not a field?
Fields are the only way to store the state of an object.
Raw access to them is required for numerous things. Setting struct layout.
Properties predate C#. They were present in COM least.
Yep, used them with classes way back in VB5 and VB6 apps.
Properties predate C#. They were present in COM least.
Oh, COM had properties? Interesting, I wasn’t aware of that!
Where would the state actual be stored if not a field?
Well, auto properties have automatically generated fields, and as you said, all properties are represented internally as get/set methods. Which seems like a bit of a kludge. Why can’t properties be defined as first class constructs that have their own internal state storage and accessor logic built in to them? Turning a property that you code into a field and two methods in the IL seems like trying to shoehorn a new feature into a legacy system without fully thinking it out. Kind of like generic type erasure in Java – C# did generics right, by having generic types remember their type parameters even at runtime. So why should properties be implemented in this roundabout fashion?
Raw access to them is required for numerous things. Setting struct layout.
If properties had their own internal state storage as I described above, you could set struct layout by manipulating the properties themselves, without the need for fields.
Not sure this is correct. Properties can be accessed via reflection and Type.GetProperty methods. Whilst they may be syntactic sugar, the sugar does far more than just expose a field level variable.
You can’t pass a property by reference
TIL. I never really encountered the need to do it.
Makes sense, when you realize it’s really a getter and a setter under the hood.
Oh, you can’t? I rarely ever found the need to, so I must have forgot about that. I wonder why that’s the case? A ref
parameter just means “if you replace the value of this parameter with some new value, the change is propagated to the caller”, right? So why can’t that be done with properties?
maybe they can be rewritten in the back end to reuse the property code
What do you think is “in the back” of that { get; set; } code? Fields.
I know. What I’m saying is, why don’t auto properties just have the data storage logic built into them, rather than being wrappers around invisible fields? And likewise, computed properties can have the computation logic built into them, rather than being wrappers around invisible methods.
Say you have a class that processes something for you. But it doesn’t contain the object it’s processing, that’s your problem. You have to give the class an object to process. So this processing class has a method with this signature: public bool DoSomethingToFoo(ref Foo f)
.
Now, you write some user class that has a public Foo Thingy { get; set; }
and you’re going to pass that Foo instance to the processor class. So you do processor.DoSomethingToFoo(ref this.Thingy);
. Suddenly, the C# compiler loses all of its shit and tells you you can’t do that. But why?!
Because Thingy
is a property, which is a function pointer, not a Foo reference. And therein lies the trap with properties. Yeah, they look like fields, and most of the time, they act like fields, but there’s a tiny amount of time when the distinction actually matters. And when you need to pass a ref
or out
parameter (and you will need this at some point), a property just won’t cut it.
Hmm. Couldn’t ref
be redesigned to either automatically dereference auto properties into their backing fields (and not work for computed properties), or pass getter/setter delegates around rather than memory addresses?
Auto properties create a hidden field to store the value in, so using properties like fields is just adding an extra step.
A property isn’t a property without a backing field, so no, we can’t get rid of them.
I was thinking that auto properties could have the equivalent of a backing field built in to them internally, rather than having one magically declared for you, but on the other hand you can’t actually reference it in code, but on the third hand if you try to declare your own field with the same name you get an error, and sometimes compiler error messages reference these backing fields even though they don’t actually exist in your code… aaaaaaaaaaaaaaaaaaaaaa! What a nightmare! At least we’re not dealing with C++ templates or C #define
directives, those are far worse!
And then of course computed properties (those with code in them) would not get a built-in backing field; rather they would get built-in get/set logic, with all the concerns I mentioned regarding backing fields addressed in the same fashion.
What is the point of properties?
We already had fields and functions.
On one hand, public fields are frowned upon because they link your internal structure to your external API. Changing your internal structure becomes a breaking change. Changing the implementation of a function from a field access to a computation is not.
On the other hand, the code ergonomics of fields is simply better than getter/setter functions.
Properties are the best of both worlds: the code ergonomics of fields with the API impact of functions.
If every property was an auto-property, we wouldn’t even need properties and could just use fields directly.
C# devs
null reference exceptions