Inconsistent accessibility with abstract classes

2019-07-01 23:24发布

问题:

I have an internal abstract class InternalClassBase and two (also internal) classes InternalClass1 and InternalClass2, which inherit from InternalClassBase.

I also have a public abstract class PublicClassBase and two (also public) classes PublicClass1 and PublicClass2, which inherit from PublicClassBase.

The PublicClassBase has a protected member XXX of type InternalClassBase, so both PublicClass1 and PublicClass2 can use it.

This is my code:

internal abstract class InternalClassBase { }
internal class InternalClass1 : InternalClassBase { }
internal class InternalClass2 : InternalClassBase { }

public abstract class PublicClassBase
{
    protected InternalClassBase XXX;  // this is where the error happens
}
public class PublicClass1 : PublicClassBase { }
public class PublicClass2 : PublicClassBase { }

Why can't PublicClassBase contain the XXX member in my example? I thought that XXX would only be visible within PublicClassBase, PublicClass1 and PublicClass2, but not outside of it.

I also thought that I understand access modifiers, but obviously I don't :)

Edit - the error happens at declaration of XXX inside PublicClassBase, and the exception message is: Inconsistent accessibility: field type 'ClassLibrary2.InternalClassBase' is less accessible than field 'ClassLibrary2.PublicClassBase.XXX', but how can protected be more accessible then internal?

回答1:

Imagine that in an assembly other than the one types from your example are declared, you declare class PublicClass3 that inherits from PublicClassBase. The field XXX should be visible from PublicClass3, since it is protected, but the type of the field is internal, so at the same time, it should not be visible from PublicClass3.

Obviously, you cannot have both, hence the error.

You can solve this either by making your field private, or making PublicClassBase and its children internal.



回答2:

Given an assembly provided by you to me, containing the classes above, I can go ahead and create a subclass of PublicClassBase in a different assembly which references yours.

In that class, I would have to implement your protected member XXX of type InternalClassBase - clearly I can't, because InternalClassBase is marked as internal.