不一致的可访问性:基类比子类更难访问

问题描述 投票:7回答:2

我正在阅读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

尝试3:Base是内部的,sub是公共的(此方法有效,但是应该会失败。因为与Sub类相比,Base的访问性较差

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()
        {
        }
    }
}
c# inheritance base-class
2个回答
11
投票

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

例如,给定:

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

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

It will进行编译是因为包装类的internal修饰符使类public上的B修饰符无意义。相反,类型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的可访问性是公共的,则M的可访问域是T的可访问域。

和可访问性域的MSDN's description

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

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


0
投票

当您从其他公共类继承私有类时,私有继承类无法在其他类中访问,因为它包含私有类的引用及其数据,因此不可能。

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

两者都是私人的。如果使用内部,则只能以汇编形式访问。

© www.soinside.com 2019 - 2024. All rights reserved.