Let's say I have a class, defined in C# like this:
public class A { public A() {} private int v1; public int P1 { get { return v1; } set { v1 = value; } } private String v2; public String P2 { get { return v2; } set { v2 = value; } } }Why is it better than this?
public class A { public A() {} public int P1; public String P2; }Given that if I can change the class code I can change the latter to use properties trivially, why is it that is better to have a lot of extra syntaxis? Do the fields show up diferently on Reflection? Does it matter? I'm not asking if it's a good idea to have trivial data objects, because sometimes its just a need. For instance, try to use CastleActiveRecord without them.
Thanks for your time, AurelianoCalvo.
There are some semantic differences between the two. For example, you can't take the address of a property. Calling += or similar operators on a property isn't an atomic operation, whereas it is for a member variable (assuming a single CPU). The reason that public member variables and properties are so similar, is for convenience. Some of that convenience comes when you need to "upgrade" from a member variable to a property. For example, you may want to validate a new value or fire an event when the value changes. Those or any other possibly unforseen need may prompt you to change from a public member variable to a property. When you do that, the semantics change in subtle ways. If you own all of the code and are able to deploy it all simultaneously, there is no significant harm. The harm comes when you are making a library that others depend on. If you change to a property, all of the code that depends on yours will either compile or not compile. If it doesn't compile (as in the case of taking the address of a property), you are safe. However, if it does compile (as in the += case), you could introduce bugs through the subtle semantics changes. Notice that you can't put a public member variable on an interface in .Net, but you can put public properties. It's mostly for this reason. Since it could cause problems in theory, Microsoft decided it was best not to allow it for interfaces, which are intended to be stable contracts. Some people saw that decision, along with trends in other languages (usually based more on a sub-typing argument rather than a versioning argument), and decided that it sould be a "best practice" to write all C# code this way. -- MichaelSparks
So, would you agree than YagNi applies in this case? How do you do to take an address of a Field in C#? I'm not even sure if the += operator is atomic. Certainly not with strings (or non primitive objects), and depends on the CLR on other platforms. For instance, does mono implement it as a single assembler operation? -- AC
Yes, I'd agree that YagNi applies here, with the caveat that if you find yourself having to think about this too often, if may point to an underlying problem with your design. I'm not opposed to having public fields on classes that don't form interfaces with code outside my control, but I very rarely encounter a need for it in well-factored code. You mentioned an ORM tool above, and that seems like a reasonable place to find public fields. In C#, you can take the address of a field using the "&" operator, as long as you're inside the initializer for a "fixed" block, which is inside an "unsafe" block. The += operator is implemented as a single instruction on the Microsoft CLR, and I'd imagine in Mono as well, but the CLR specifications don't make any guarantee that it is atomic. Even the Microsoft CLR won't make that atomic on a multi-core or multi-proc x86 machine. I was trying to point out that even though your customer's code may be buggy, it could be your change that would expose their bug. I don't tend to worry about stuff like that in my code, but when you're Microsoft, designing the .Net framework, it is probably something you think about. -- MichaelSparks
I do agree that changing a field to a property might change this kind of things. But I don't see the difference to other refactoring (which are also prone to this). For instance, changing a = a + 1 to a++ might have the same problems (might not if the compiler is optimizing). -- AC
(a few minutes later, after re-reading the page) You pointed out a big semantic difference between public fields and properties in your original post, and I failed to comment on it. Reflection does differentiate the two. -- MichaelSparks
Well, my understanding is that, because properties and fields can be used with the same syntax, there should be a way to use them in a uniform way via reflection. If this can't be done with the .Net reflection library would must be trivial to do that. I mean, as a programmer I would like to be able to think they are the same in some contexts. I do agree that this change might break some things, what I want to know is why avoiding possible break justifies writting some much extra code, which has to be read and written and might have its own problems. Well, I think we agree that it's not worth the effort. -- AC
For you and me, the slight possibility of breakage doesn't justify writing extra code, especially when the breakage could easily have been avoided by our customers being slightly smarter. For Microsoft, writing the .Net framework, it matters. If they cause breakage between 1.1 and 2.0 frameworks via this, they will never hear the end of it. You'd think that people would know better than to do things like take the address of one of their fields, etc, but with several million monkeys, you will get a good number of people who will do it for whatever reason. Microsoft spends a large amount of their time dealing with backwards compatibility. When they ship a new .Net framework, they don't just cross their fingers and hope that it doesn't cause breakage. They enumerate all of the possible breakage points and make decsions about what to include based on how much potential breakage there will be, taking into considersation the possibility of stupid customers. A hard and fast rule to never have public fields, will eliminate entire classes of breakage from their consideration. For them, it is a good idea. -- MichaelSparks
Some discussion moved to XpAndPublishedInterfaces