Are protected members/fields really that bad?

Regarding fields vs. properties, I can think of two reasons for prefering properties in the public interface (protected is also public in the sense that someone else than just your class can see it).

  • Exposing properties gives you a way to hide the implementation. It also allows you to change the implementation without changing the code that uses it (e.g. if you decide to change the way data are stored in the class)

  • Many tools that work with classes using reflection only focus on properties (for example, I think that some libraries for serialization work this way). Using properties consistently makes it easier to use these standard .NET tools.

Regarding overheads:

  • If the getter/setter is the usual one line piece of code that simply reads/sets the value of a field, then the JIT should be able to inline the call, so there is no performance overhad.

  • Syntactical overhead is largely reduced when you're using automatically implemented properties (C# 3.0 and newer), so I don't think this is an issue:

    protected int SomeProperty { get; set; }
    

    In fact, this allows you to make for example set protected and get public very easily, so this can be even more elegant than using fields.


Are protected members/fields really that bad?

No. They are way, way worse.

As soon as a member is more accessible than private, you are making guarantees to other classes about how that member will behave. Since a field is totally uncontrolled, putting it "out in the wild" opens your class and classes that inherit from or interact with your class to higher bug risk. There is no way to know when a field changes, no way to control who or what changes it.

If now, or at some point in the future, any of your code ever depends on a field some certain value, you now have to add validity checks and fallback logic in case it's not the expected value - every place you use it. That's a huge amount of wasted effort when you could've just made it a damn property instead ;)

The best way to share information with deriving classes is the read-only property:

protected object MyProperty { get; }

If you absolutely have to make it read/write, don't. If you really, really have to make it read-write, rethink your design. If you still need it to be read-write, apologize to your colleagues and don't do it again :)

A lot of developers believe - and will tell you - that this is overly strict. And it's true that you can get by just fine without being this strict. But taking this approach will help you go from just getting by to remarkably robust software. You'll spend far less time fixing bugs.

And regarding any concerns about performance - don't. I guarantee you will never, in your entire career, write code so fast that the bottleneck is the call stack itself.


OK, downvote time.

  • First of all, properties will never hurt performance (provided they don't do much). That's what everyone else says, and I agree.

  • Another point is that properties are good in that you can place breakpoints in them to capture getting/setting events and find out where they come from.

The rest of the arguments bother me in this way:

  • They sound like "argument by prestige". If MSDN says it, or some famous developer or author whom everybody likes says it, it must be so.

  • They are based on the idea that data structures have lots of inconsistent states, and must be protected against wandering or being placed into those states. Since (it seems to me) data structures are way over-emphasized in current teaching, then typically they do need those protections. Far more preferable is to minimize data structure so that it tends to be normalized and not to have inconsistent states. Then, if a member of a class is changed, it is simply changed, rather than damaged. After all, somehow lots of good software was/is written in C, and that didn't suffer massively from lack of protections.

  • They are based on defensive coding carried to extremes. It is based on the idea that your classes will be used in a world where nobody else's code can be trusted not to goose your stuff. I'm sure there are situations where this is true, but I've never seen them. What I have seen is situations where things were made horribly complicated to get around protections for which there was no need, and to try to guard the consistency of data structures that were horribly over-complicated and un-normalized.