8

I am reading book "C# 4.0 in a nutshell" by Joseph Albabari and Ben Albabari. From there I find a topic restrictions on access modifiers. Page 91, Topic "Restrictions on Access Modifiers".

Quoting from the book.

The compiler prevents any inconsistent use of access modifiers. For example, a sub- class itself can be less accessible than a base class, but not more

So this says that base class should be equally or more accessible than subclass. So if base class is internal then subclass should be either private or internal. If base class is private and sub class is public then compile time error will be generated. While trying this in Visual Studio I found some strange behavior.

Try 1: Base is private and sub class is private (Works, right behavior) This also works if both are internal, public.

private class A { }
private class B : A { }         // Works

Try 2: Base is private and sub class is public or internal (This fails, right behavior)

private class A { }
public class B : A { }          // Error

Try 3 : Base is internal and sub is public (This works, but it should fail. As Base is less accessible than sub class

internal class A { }
public class B : A { }          // Works, but why

Now my question is why Try 3 didn't failed? Sub class is public and is more accessible than base class which is internal. Even the book says this should fail. But Visual Studio compiled this successfully. This should work or not?

Edit:

I created a new Console Project in VS. In Program.cs I added my code. Here is complete code of Program.cs file.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        internal class A { }
        public class B : A { }          // Error

        static void Main()
        {
        }
    }
}
fhnaseer
  • 7,159
  • 16
  • 60
  • 112
  • Technically, `internal` _can_ be exposed for use outside the assembly via the [InternalsVisibleTo attribute](http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx) so perhaps this is the reasoning behind it. I'll see if I can find a specific entry in the C# specification. – Chris Sinclair May 20 '13 at 12:50
  • Try 3 works for me, ie. fails to compile with inconsistent accessibility error. – amnezjak May 20 '13 at 12:51
  • I also thought of InternalsVisibleTo attribute, but what if I don't mention this in my assembly file. There must be another reason for this. – fhnaseer May 20 '13 at 12:51
  • Actually, I just did a copy/paste test of your "Try 3" in LINQPad and it failed (inconsistent accessibility error); are you _sure_ what you posted is what you have compiled in visual studio? – Chris Sinclair May 20 '13 at 12:52
  • @amnezjak You mean that you received error when you compiled try 3? – fhnaseer May 20 '13 at 12:52
  • @ChrisSinclair yes. I created a new console project and pasted these lines. And it didn't gave any compilation error. – fhnaseer May 20 '13 at 12:53
  • @well that's strange. My Program.cs file contain only these lines and main function. And it compile successfully. – fhnaseer May 20 '13 at 12:54
  • @ChrisSinclair but it should give compilation error. As sub class is more accessible than base class. – fhnaseer May 20 '13 at 12:56
  • I can confirm the same behavior as @ChrisSinclair: I don't get your third example to compile. It fails with _"Inconsistent accessibility: base class 'Namespace.A' is less accessible than class 'Namespace.B'"_. – Fredrik Mörk May 20 '13 at 12:56
  • @ChrisSinclair I have edited the question. Whole code is present there. – fhnaseer May 20 '13 at 12:56
  • @FredrikMörk then why I am not receiving this error? – fhnaseer May 20 '13 at 12:58
  • @FaisalHafeez See the answer by Chris. I was writing the same thing as he posted it :-) – Fredrik Mörk May 20 '13 at 12:59
  • 6
    As a side note, this question works as a schoolbook example of why Jon Skeet always stresses that you should include a "short, but _complete_" program in the question. Once the question was edited, the problem was obvious. Before that, a mystery :-) – Fredrik Mörk May 20 '13 at 13:01
  • Well these are those minor mistakes which are not easy to find. You keep on finding, finding and finding. And in the end you come to know that oh this was the mistake. – fhnaseer May 20 '13 at 13:03
  • 2
    Here's a puzzle for you to see if you understand the rule. `public class Alpha { protected internal class Bravo {} }` in assembly Alpha.DLL, and `public class Charlie : Alpha { xxx class Delta : Bravo {} }` in assembly Charlie.DLL. What are the legal values of accessibility modifier `xxx`? – Eric Lippert May 20 '13 at 14:57
  • @EricLippert Delta class will be private. – fhnaseer May 21 '13 at 04:40
  • @FaisalHafeez [It's a trap!](http://haacked.com/archive/2007/10/29/what-does-protected-internal-mean.aspx) – Chris Sinclair May 21 '13 at 10:08

2 Answers2

12

You are placing your nested classes within another internal class.

For example, given:

class Program
{
    static void Main(string[] args)
    {
    }

    internal class A { }
    public class B : A { }
}

It will compile because the internal modifier of the wrapping class makes the public modifier on class B moot. Rather, type B's accessibility is limited by its wrapped class Program -- its accessibility domain is internal as well.

If you update it to be:

class Program
{
    static void Main(string[] args)
    {
    }
}

internal class A { }
public class B : A { }

It will throw the inconsistent visibility compiler error. Or if you redefine Program to be public instead of internal it will also throw the error. In this case, B's accessibility domain is now public and no longer limited by Program's internal accessibility domain.


From the C# specification 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.

And the MSDN's description of Accessibility Domain:

If the member is nested within another type, its accessibility domain is determined by both the accessibility level of the member and the accessibility domain of the immediately containing type.

If the wrapping type Program is internal, then the nested type B being public will have its accessibility to match Program, thus it is treated as internal and no compiler error is thrown.

Chris Sinclair
  • 22,858
  • 3
  • 52
  • 93
0

private inherited classes can not accessible in other classes when you inherit private class with other public class then it contains the reference of private class and its data so it is not possible.

abstract class test
    {
        public abstract void add();
        public int num1;
        public string str;
    }
class test3 : test1
    {
        public override void add()
        {
            throw new NotImplementedException();
        }
    }

both classes are private. if you use internal then you can access only in assembly.