From section 3.5 of the C# 4 spec:
Declarations of members allow control over member access. The accessibility of a member is established by the declared accessibility (§3.5.1) of the member combined with the accessibility of the immediately containing type, if any.
...
Access to a member is permitted when the textual location in which the access takes place is included in the accessibility domain (§3.5.2) of the member.
Then in section 3.5.2 (accessibility domains):
The accessibility domain of a nested member M declared in a type T within a program P is defined as follows (noting that M itself may possibly be a type):
- If the declared accessibility of M is public, the accessibility domain of M is the accessibility domain of T.
- ...
- If the declared accessibility of M is private, the accessibility domain of M is the program text of T.
This is the case here. So the accessibility domain of DoSomething is the accessibility domain of PrivateInnerClass by the first bullet... but the accessibility domain of PrivateInnerClass is the program text of OuterClassBase by the final bullet.
Therefore the call within OuterClassDerived is not in the accessibility domain of DoSomething, so it can't call it.
I'm actually surprised that you can derive ProtectedInnerClass from PrivateInnerClass in the first place...
EDIT: And it turns out you can't... even having removed the OuterClassDerived class entirely, you get this error:
Test.cs(10,21): error CS0060: Inconsistent accessibility: base class 'OuterClassBase.PrivateInnerClass' is less accessible than class 'OuterClassBase.ProtectedInnerClass'
This violates section 10.1.4.1 of the specification:
The direct base class of a class type must be at least as accessible as the class type itself (§3.5.2). For example, it is a compile-time error for a public class to derive from a private or internal class.
Here you're trying to derive a protected class from a private class - the protected class is more accessible than the private class, hence the error.
PrivateInnerClassprotectedwill allow it to compile.OuterClassDerivedis a red herring here - your protected subclass doesn't compile on its own! (Just get rid of the second half of the program - the first half still doesn't compile.)