0

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...

6
  • 1
    I assume OuterClassDerived should be OuterClassDerived : OuterClassBase? Commented Jul 20, 2012 at 20:51
  • That's just basic scope rules in C#. Public scope is accessible outside the class. Private scope is accessible inside the class. Protected scope is available inside the class and in derived classes. Commented Jul 20, 2012 at 20:53
  • Counter-Intuitive? How so, if you could access a private class outside of the scope it was defined in, now that would be counter intuitive. Commented Jul 20, 2012 at 20:58
  • Making PrivateInnerClass protected will allow it to compile. Commented Jul 20, 2012 at 20:58
  • 1
    The whole of OuterClassDerived is 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.) Commented Jul 20, 2012 at 21:16

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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).

2 Comments

But the subclassing happens inside of the class X that can access PrivateInnerClass. That is, X owns PrivateInnerClass, so why would this be a problem? As such, I don't get why this breaks the private constraint.
@trinithis PrivateInnerClass.DoSomething is private to OuterBaseClass (because PrivateInnerClass is private), any code that let you access PrivateInnerClass.DoSomething from outside OuterBaseClass is illegal because no one, not even OuterBaseClass is allowed to undo the constraints of the PrivateInnerClass deceleration
0

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(); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.