不一致的可访问性:基类的可访问性低于子类

本文关键字:访问 子类 基类 不一致 于子类 | 更新日期: 2023-09-27 18:14:20

我正在阅读Joseph Albabari和Ben Albabari合著的《c# 4.0简介》一书。从那里我发现了访问修饰符的主题限制。第91页,主题"访问修饰符的限制"

引自书中。

编译器防止任何不一致的访问修饰符的使用。为例如,子类本身可能比基类更难访问,但不能更多

这就是说基类应该和子类一样或更容易访问。因此,如果基类是内部的,那么子类应该是私有或内部的。如果基类是私有的,而子类是公共的,则会生成编译时错误。当我在Visual Studio中尝试这个时,我发现了一些奇怪的行为。

尝试1:基是私有的,子类是私有的(工作,正确的行为)这也适用于如果两者都是内部的,公共的

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

尝试2:基类是私有的,子类是公共的或内部的(这失败了,正确的行为)

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

Try 3: Base是internal and sub是public(这是有效的,但它应该失败。As基类比子类

更难访问
internal class A { }
public class B : A { }          // Works, but why

现在我的问题是为什么尝试3没有失败?子类是公共的,比基类更容易访问,基类是内部的。就连书里都说这应该失败。但是Visual Studio成功地编译了它。这应该起作用吗?

编辑:

我在vs中创建了一个新的控制台项目。在Program.cs中我添加了我的代码。这里是Program.cs文件的完整代码。

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

不一致的可访问性:基类的可访问性低于子类

您正在将您的嵌套类放置在另一个internal类中。

例如:

class Program
{
    static void Main(string[] args)
    {
    }
    internal class A { }
    public class B : A { }
}

编译,因为包装类的internal修饰符使B类上的public修饰符无效。相反,类型B的可访问性受到其包装类Program的限制——它的可访问域也是internal

如果您将其更新为:

class Program
{
    static void Main(string[] args)
    {
    }
}
internal class A { }
public class B : A { }

将抛出不一致可见性编译器错误。或者,如果您将Program重新定义为public而不是internal,它也会抛出错误。在这种情况下,B的可访问域现在是public,不再受Programinternal可访问域的限制。


来自c#规范3.5.2 Accessibility Domains:

在类型T中声明的嵌套成员M的可访问域在一个程序中,P的定义如下(注意M本身可以可能是一个类型):

如果M声明的可访问性是公共的,则M的可访问域是t的可访问域。

和MSDN对无障碍域的描述:

如果成员嵌套在另一个类型中,则其可访问域由成员的可访问性级别和直接包含类型的可访问性域。

如果包装类型Programinternal,则嵌套类型Bpublic将具有匹配Program的可访问性,因此它被视为internal,并且不会抛出编译器错误。

私有继承类不能在其他类中访问,当你与其他公共类继承私有类时,它包含了私有类的引用和它的数据,所以这是不可能的。

abstract class test
    {
        public abstract void add();
        public int num1;
        public string str;
    }
class test3 : test1
    {
        public override void add()
        {
            throw new NotImplementedException();
        }
    }
两个类都是私有的。如果使用internal,则只能在汇编中访问。