A group blog from members of the VB team
The other day I got an email from a developer asking an interesting question about VB10’s Auto-implemented Properties feature.
“I am, however, somewhat confused regarding the properties feature you mentioned - i.e. turning 11 lines of get/set/backing variable into one line. Wouldn't this be exactly the same as the existing functionality of creating a public variable? I see no benefit for using a property in this case, except perhaps for the sake of what some would consider best practice.”
On the surface there doesn’t seem to be a big difference between this:
Public Property Name() As String
Public Name() As String
Clearly both will expose an object’s state to the outside world, and can be read/modified using the exact same syntax. Which then begs the question, why would I ever use a property if I have no special logic in the Getter/Setter?
Let’s consider some reasons:
1. Fields can’t be used in Interfaces
You can’t enforce the existence of a field in an object’s public contract through an interface. For properties though it works fine.
While your application currently may not require any validation logic to set a particular value, changing business requirements may require inserting this logic later. At that point changing a field to a property is a breaking change for consumers of your API. (For example if someone was inspecting your class via reflection).
3. Binary Serialization
Changing a field to a property is a breaking change if you’re using binary serialization. Incidentally, this is one of the reasons VB10’s auto-implemented properties have a “bindable” backing field (i.e. you can express the name of the backing field in code) – that way, if you change an auto-implemented property to an expanded property, you can still maintain serialization compatibility by keeping the backing field name the same (in C# you’re forced to change it because it generates backing fields with unbindable names).
4. A lot of the .NET databinding infrastructure binds to properties but not fields
I’ve heard arguments on both sides as to whether or not that’s a good thing, but the reality is that’s the way it works right now.
5. Exposing a public field is an FxCop violation
For many of the reasons listed above :)
One argument I’ve heard for using fields over properties is that “fields are faster”, but for trivial properties that’s actually not true, as the CLR’s Just-In-Time (JIT) compiler will inline the property access and generate code that’s as efficient as accessing a field directly.
For these reasons and more, in most cases you’re better off using a property rather than exposing a public field. Thankfully VB10 will make this a lot easier :)
Can auto-implemented properties specify gets and sets on different scopes other than public like in C#?
If you're talking about something like a public get and a private set, then no, that isn't supported by Auto-Implemented Properties. You'd have to expand the syntax to standard property syntax to mix access modifiers on the Get and Set procedures.
Another reason is that if you change a public field into a property, you break binary compatibility.
So, in VB10, we'll almost be back to the power of VB6? In VB6 you could change a public field to a public property without any of those problems - didn't break binary compatibility, interfaces could contain fields, and data-binding liked both.
Note that your field definition is actually an array:
Public Name As String
Visual studio can easily create the properties out of your fields, and regions can be used to unclutter your code, thus the tedious work of creating properties is reduced and you get the benefits described above. Somehow I don't like having public fields, fields should remain private, at least from OOP point of view. In my opinion the field should not even allow the access modifier public.
I've got to agree with MarkJ. The differences between a field and a property seem artificial to me. Personally, I like to use a field when the value is "simple" and a property when it needs to have some "smarts" to it. That way the next person to read the code can tell if anything special is happening without reading through all those lines of code.
Unfortunately, I can't follow that rule largely because of issue 4 above. (The others almost never come up for me.) I can't understand why that is, though. If the compiler wants me to have a second, private variable then why can't it just make one for itself in the CLR code?
I agree that use a public member variable if you do not need any extra functionality. One can avoide the set function on most properties by only letting it get initialized in a constructor. That constructor would take more than one argument and initialize more than one member variable.
Exposing a field as a property to only facilitate reflection and automatic unit testing is not always a good thing.
If you can't set different scopes for the get and set operations this feature loses a lot of its appeal to me. Just my opinion.
Different scopes seems to me to be a very common use case.... (Public getter, private or protected setter) ...and wouldn't require a lot of compiler gymnastics to accomplish. Too bad.
“fields are faster”, but for trivial properties that’s actually not true -
For me that summs upnmy problem with the Class Oriented Programming - So many of the changes over recent years facillitate trivial isuues but impede free thinking. For example, one can flip and rotate images - something any elementary programmer can easily do and has a library to do it. But, because pointers have really been lost te faster and non-trivial mehodsof image processing are lost. Assembler is hampered. And yet because globals are free of GC activity we dont need complicated and confusing pointer types - just the ways to get and set them. Until MS gives them back to me I'll not waste my money on further VS versions. Why should I if I get trivial solutions and you deny my real needs. This must largely apply to C# too. I know, you think we are dummies and have to be protected from catastrophic errors. Thats why C++ is a dogs dinner. Sorry guys, but I'm the programmer. You are supposed to be the facillitator for all my gambles.
Ok, I tried to read this with objectivity as I do believe that properties have a value over fields. Mostly, because of validation, serialization, and lazy initialization. However, three of the five reasons provided relate to how the compiler and/or library was designed and implemented. A very weak argument.
Considering auto properties over full properties, I prefer to have full properties from the get go and tools such as Resharper and CodeRush make that just about as easy to put into place. Auto properties do the same thing, expand into properties with backing fields. It just happens during a preprocessing step and is transparent to the developer.
Using the right tools for the job is one of the main responsibilities of being a programmer. Something it sounds like Ron has sadly forgotten. Managed code has a very viable position within the domain of computer languages. However, if you need to do something that requires a different language set then a different language should be used for the task.
Different scopes for the get and set, ah yes! Very useful. And, once again, it was supported in VB6. Can we have it back please?
For gods sake will you VB6 lovers just put a sock in it. Yes VB6 does have SOME things that VB.NET has but VB.NET as I'm sure you know does not work in the same way that VB6 does and therefore has had to be pretty much built from the ground up from what I understand. These guys at MS have deadlines and schedules and considering the massive amount of things you can do in VB.NET I would say that not having some minor things that VB6 had is well worth it. If you dont like .NET that much then use VB6... just stop cluttering every single VB.NET blog/post/tutorial on the internet with sarcastic comments.
VB.NET supports different accessiblity modifiers for Get/Set within a property:
Property Name as string
Regarding the ability to do this in auto-implemented properties, I definitely agree that'd be useful. If anyone has suggestions on the syntax they'd want for specifying this I'd be very interested to see it :)