1

I do not understand the accessibility limitations exhibited below

public abstract class Base { }
internal class Common : Base { }
public class Instance : Common { }

This won't compile.

Inconsistent accessibility: base class 'Common' is less accessible than class 'Instance'

I can accomplish what I wanted with public abstract class Common but why can't I simply not expose the name at all?

Edit: What I'm asking is WHY it works this way! Everyone is answering with what the rules are, not explaining why the rules are that way.

Loren Pechtel
  • 8,945
  • 3
  • 33
  • 45

3 Answers3

3

Inheritors of a class cannot widen the scope of accessibility of the base class.

public: Access not limited internal: Access limited to this program

Once limited to the program, all inheritors of a, internal class must remain internal or assume lesser accessibility (protected internal or private).

Per the C# specification, section §3.5.4 Accessibility constraints:

The parameter types of an instance constructor must be at least as accessible as the instance constructor itself.

In the example

class A {...}

public class B: A {...}

the B class results in a compile-time error because A is not at least as accessible as B.

Also:

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.

If you are trying to create a Common class with functionality you prefer not to make accessible to external code, you should prefer composition over inheritance. For example:

public abstract class Base
{
...
}

internal class Common : Base
{
...
}

public class Instance
{
    internal Instance(Common common)
    {
        ...
    }
...
}
Community
  • 1
  • 1
Ed Chapel
  • 6,842
  • 3
  • 30
  • 44
  • Note that the bit about the instance constructor and parameter types isn't specfically relevant to the question nor the code snippet, it's just the last bullet point of many in that particular section. The relevant bullet point here is actually the first one, which matches the second quoted portion that is found later in the spec. – Anthony Pegram Jan 05 '12 at 06:00
2

It's a matter of how visible the code is to other assemblies. By making Common internal you're limiting access to Common to its assembly whereas by making Instance public you're making Instance accessible to any referencing assembly. If a referencing assembly can't access a type's base class how could it access any members inherited from that base class?

Dave Fancher
  • 376
  • 1
  • 4
0

If Common contained a property, lets say Foo:

public string Foo { get; set; }

than the Instance class would automatically expose that property. You can think of it this way:

public void Test()
{
    Common myInstance = new Instance();
    System.Console.WriteLine(myInstance.Foo);
}

Since Instance needs to expose everything Common has, the access modifier on the base class cannot be less exposed.

You could, however, create the property Foo as internal to accomplish much the same.

mbursill
  • 2,911
  • 1
  • 32
  • 44