First, protected
is no guarantee of privacy, unless the only consumable class in your inheritance chain is sealed (i.e. all base classes are internal to the assembly). Any developer who knows ANYTHING about OOP can derive your class and expose all your internals to the world.
Using internal
on members instead usually solves this problem; only YOUR code, located in the same assembly you're developing, can see an internal member. The public children you expose for the use of others can be derived from outside the assembly, but the internals you want hidden are still hidden. Developers creating children or other objects in the same assembly should be communicating with you as to what they're using, if your internals really are that sensitive from a runtime perspective. Remember that protected internal
means protected OR internal, not protected AND internal.
Second, protected
generally indicates some flaw in class design, especially if both protected and public are used. If you have a secret, but you have to share it with your children, it's not much of a secret and it should probably be public. If it's REALLY a secret, your children shouldn't be trusted with it, because unless you give your kids a vasectomy with the sealed keyword, you can't stop them from telling THEIR children, who may no longer think it's much of a secret and share it with their household or the world.
Using protected
is not terrible, it just does not accomplish what many developers want to use it for; to make a class's innards accessible to "trusted" individuals without risking exposure of delicate internal processes. It's less access control and more access suggestion; by using protected, you are stating that this method is useful for children, but that by itself it doesn't do much good to non-children, or would be harmful to the class if exposed and misused. That's pretty much like posting a sign in your front yard that says "My door is locked, and I'm not going to give you the key, but all my kids have one". That's not even the half of it, because a "burglar" can MAKE one of your kids and use them to unlock the door.
A common and well-accepted use of protected
on methods is for Template Method classes; these are abstract classes that have a public skeletal workflow, but allow or require extension of specific pieces of their functionality to be useful. These pieces of functionality are generally highly cohesive and minor. The pattern would expose a public, non-virtual "driving function", and several handles to "helpers" as protected abstract or virtual methods. This allows consumers to derive the class and implement the helpers.
In that case, you usually don't care about the child implementation, and don't want to restrict the possible solutions; children may need public wrappers for the helper methods in order to communicate with THEIR dependencies.
protected
is also the most straightforward way to unit-test the innards of a class. Unit testing is a good thing, but if you want to write a test fixture that exercises a method, that method must be accessible from outside the class. Private is simply a no-go. Internal usually presents a similar problem. To allow innard testing at all, they have to be at least protected, so that you can derive the class FOR THE EXPRESS PURPOSE of exposing the innards. Otherwise you need some really oogly reflection to extract a MethodInfo of your private method and invoke it (along with SkipVerification CAS permissions).