C# offers the composed access modifiers “protected internal”. With C# 7.2 a new composed access modifier was added: “private protected”. Unfortunately, these modifiers are hard to understand as their names don’t reflect their meaning. Within this article I want to explain the two modifiers and their technical background.
Within the CLR you will find the single access modifiers “Family” and “Assembly”. “Family” means that this object or a derived object has access. Within C# and many other programming languages this “Family” modifier is implemented with the “protected” keyword. The CLR “Assembly” modifier means that a member is accessible by everyone within the defining assembly. The according implementation in C# is done with the “internal” keyword. So far, as we have the single modifiers it is quite easy. But what if we combine those two modifiers?
Within the CLR it stays simple. It offers two compound access modifiers: “Family and Assembly” and “Family or Assembly”. It combines the single modifiers by “And” to create an intersection or by “Or” to create a union.
“Family and Assembly” will allow access from objects of this assembly in case they are derived objects.
“Family or Assembly” will allow access from everyone object within the defining assembly and additional by any derived object outside of the assembly.
In C# things become difficult as they choose an awkward syntax. At first, the support for the “Family or Assembly” CLR access modifier was added to C#. But the C# syntax was not “protected and internal” it was “protected internal” without the “and”. I think that’s a good choice as it keeps things simple. The “and” keyword would be disturbing and unnecessary.
But with C# 7.2 the “Family and Assembly” CLR access modifier should become a part of C#. Now the language designers had the issue that the “protected internal” modifier without the “and” keyword was still part of the language. So how should they name the new modifier? If they choose a syntax like “protected or internal” it would be easy to understand but with the downside of the implicit interpretation of “protected internal” as “protected AND internal” and therefore with the risk that developers by mistake use the wrong modifier as they have nearly the same syntax.
So, the language designers decided to use the syntax “private protected”. This should mean we have the well-known protected relationship between base and derived object and additional the “private” keyword means that this relationship is limited to derived objects of the same assembly. In my opinion that wasn’t a good decision. Of course, the composed keywords are now different and cannot be mixed up by mistake, but they are awkward and confusing as they don’t reflect their meaning.
But of course, we should not criticize this decision too much because it was a decision between bad alternatives only. There was no possibility to add the “Family and Assembly” feature in a clean way. The crucial mistake was already done as the “Family or Assembly” feature was added to C#. The language designers choose a syntax without respect to the possibility that the “Family and Assembly” feature will be added in future.