Are protected members/fields really that bad?

2019-01-06 13:40发布

问题:

Now if you read the naming conventions in the MSDN for C# you will notice that it states that properties are always preferred over public and protected fields. I have even been told by some people that you should never use public or protected fields. Now I will agree I have yet to find a reason in which I need to have a public field but are protected fields really that bad?

I can see it if you need to make sure that certain validation checks are performed when getting/setting the value however a lot of the time it seems like just extra overhead in my opinion. I mean lets say I have a class GameItem with fields for baseName, prefixName, and suffixName. Why should I take the overhead of both creating the properties (C#) or accessor methods and the performance hit I would occur (if I do this for every single field in an application, I am sure that it would adds up at less a little especially in certain languages like PHP or certain applications with performance is critical like games)?

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

Public and/or protected fields are bad because they can be manipulated from outside the declaring class without validation; thus they can be said to break the encapsulation principle of object oriented programming.

When you lose encapsulation, you lose the contract of the declaring class; you cannot guarantee that the class behaves as intended or expected.

Using a property or a method to access the field enables you to maintain encapsulation, and fulfill the contract of the declaring class.



回答5:

I agree with the read-only property answer. But to play devil's advocate here, it really depends on what you're doing. I'll be happy to admit i write code with public members all the time (i also don't comment, follow guidelines, or any of the formalities).

But when i'm at work that's a different story.



回答6:

It actually depends on if your class is a data class or a behaviour class.

If you keep your behaviour and data separate, it is fine to expose the data of your data classes, as long as they have no behaviour.

If the class is a behaviour class, then it should not expose any data.