views:

1574

answers:

4

Is it recommended to set member variables of a base class to protected, so that subclasses can access these variables? Or is it more recommended to set the member variables to private and let the subclasses get or set the varible by getters and setters?

And if it is recommended to use the getters and setters method, when are protected variables used?

+13  A: 

This is very similar to this question, about whether to access information within the same class via properties or direct access. It's probably worth reading all those answers too.

Personally, I don't like any fields to be non-private with the occasional exception of static readonly fields with immutable values (whether const or not). To me, properties just give a better degree of encapsulation. How data is stored is an implementation decision, not an API decision (unlike properties). Why should class Foo deriving from class Bar care about the implementation of class Bar?

In short, I'd always go for properties, and I don't use protected variables for anything other than throwaway test code.

With automatically implemented properties in C# 3.0, it's easier than ever before to turn fields into properties. There's precious little reason not to do it.

Jon Skeet
A: 

This is a trade-off here. Setters and getters are somewhat slower than accessing fields directly, so if you are doing heavy maths and read/write these fields a lot in your subclasses, you should go for accessing the fields directly. But this is more like an exception.

Normally, you should mark them as private and go for getters/setters.

So my answer is: direct access for heavily used fields, getters/setters otherwise. Use common sense.

EDIT: I did some profiling and apparently even in Release mode, there can be up the 20% speed difference between fields and properties. See my test case here: http://pastebin.com/m5a4d1597

DrJokepu
If there's no logic within the property, in release mode the JIT will inline the property access anyway, so there shouldn't be any performance hit.
Jon Skeet
I've profiled it at length; there is no performance penalty with direct (trivial) properties; in some tests, it actually got faster, but I suspect that was cosmic rays interfering with the test ;-p
Marc Gravell
I've tried your test (using Stopwatch and 10x the iterations to get better timing). I don't see a 20% difference - but I do see a ~5% change, which surprises me. Looking into it more...
Jon Skeet
@Greg: I think the test is mostly reasonable. Just because there are ways of speeding it up doesn't mean it doesn't make an interesting point. The compiler should be able to inline the properties regardless. I tried making the fields private, and the properties didn't speed up.
Jon Skeet
(I haven't tried sealing the class yet. That's certainly interesting. I'm currently trying ints instead of doubles.)
Jon Skeet
Re your pastebin: my results (release, console, etc):Field: 00:00:14.0712500Property: 00:00:14.2500000That falls into the scale of ignorable...
Marc Gravell
@Greg: I'm using a vanilla .NET 3.5SP1 installation, compiled on the command line with "csc /o+ /debug- Test.cs"
Jon Skeet
On my slightly outdated office desktop, I repeatedly get Field: 05.5xx Property: 06.5xx. Ok, that's not 20% but you got the idea.
DrJokepu
Hmmm... OK something weird is going on. Now it's always running in exactly 3.13 seconds for either fields or properties, irrespective of sealed or protected, even with the same compilation command. So ignore my earlier comments... I'll delete them.
Greg Beech
Will I get my so-big-bullshit-that-even-the-guy-who-posted-the-answer-originally-did-not-believe-it-but-actually-turned-out-to-be-true-in-the-end badge then? :)
DrJokepu
I get around a 10% difference.
ICR
Looking at the disassembly the properties do seem to be inlined, but the order of some of the instructions is shifted about a bit (load x then mul by y vs. load y then mul by x). They are in different registers, though I can't see this causing a 5-10% difference.
ICR
Yup, I'd put money on it being different optimisation paths through this specific implimentation.
ICR
My post on where the extra 5-10% comes from can be found at http://icr.ac.webfusion.co.uk/post/Make-sure-you-know-what-youre-measuring.aspx
ICR
+2  A: 

Classes in other assemblies can derive from your unsealed classes and can access protected fields. If you one day decide to make those fields into properties, those classes in other assemblies will need to be recompiled to work with the new version of your assembly. That's called "breaking binary compatibility", and is perhaps the one solid reason why you shouldn't ever expose fields outside of an assembly.

Daniel Earwicker
A: 

I have to agree with Jon.

But, I use protected variable for "top most" inheritance class sometime in some condition. Example, if you have an object that is readonly and you cannot set it back BUT that you can use it in a child class, I do not see why I should have a protected Get to have access to that variable. A simple protected variable do the same encapsulation because you cannot set this variable and you can access this variable only from the child class.

But set/get is the way to do for other situation.

Daok
It doesn't have the same encapsulation - it specifies that now and forever, that data will be stored in a field with that name. Any change to that implementation decision is a breaking change. Often it's okay to live with that, but I prefer not to :)
Jon Skeet
Yeah the same is right for the name of the Getter ;) I prefer not, but I think in some occasion it's not that much evil to do it ;)
Daok
I'd argue that the name of the getter is part of the API, however - whereas the choice of storage is an implementation issue.
Jon Skeet