Reputation: 1
Why can't users of subclasses of private classes access public member data of the private class? The following seems very counter-intuitive to me in that it won't compile:
public class OuterClassBase {
private class PrivateInnerClass {
public void DoSomething () {}
}
protected class ProtectedInnerClass : PrivateInnerClass {}
}
public class OuterClassDerived : OuterClassBase {
public OuterClassDerived () {
ProtectedInnerClass o = new ProtectedInnerClass();
o.DoSomething(); // inaccessible due to its pretection level
}
}
Making PrivateInnerClass
public/protected allows the code to compile...
Upvotes: 0
Views: 2563
Reputation: 43036
The protected class cannot inherit from the private class for the same reason that public classes cannot inherit from internal classes: A class cannot be more accessible than its base class.
But why are you trying to do this? You can keep other classes from inheriting directly from the PrivateInnerClass, but only if they're in a different assembly. You could also do something like this; the framework does it a lot with internal/public classes:
public class OuterClassBase
{
private class PrivateInnerClass : ProtectedInnerClass
{
}
protected abstract class ProtectedInnerClass
{
public void DoSomething() { }
}
protected ProtectedInnerClass ProtectedInnerClassFactoryMethod()
{
return new PrivateInnerClass();
}
}
public class OuterClassDerived : OuterClassBase
{
public OuterClassDerived()
{
ProtectedInnerClass o = ProtectedInnerClassFactoryMethod();
o.DoSomething();
}
}
Upvotes: 0
Reputation: 1499740
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.
Upvotes: 4
Reputation: 29584
PrivateInnerClass is private to OuterClassBase - no one except OuterClassBase can use it (this is the meaning of private).
Subclassing it doesn't change the rules, it is still private - if the subclassing will break the private constraint and allow someone outside of OuterBaseClass to access members of PrivateInnerClass than this is illegal and won't compile.
In other word if something is declared private than it is private, any trick that would allow you to by pass the private declaration should not compile (except reflections).
Upvotes: 2