如何防止具有公共派生类的抽象类在其他程序集中继承?

pen*_*tur 6 c# inheritance public access-modifiers internal

我想写下面的内容:

    internal class InternalData
    {
    }

    public class PublicData
    {
    }

    abstract internal class Base {
        internal Base() { }

        private static InternalData CreateInternalDataFromPublicData(PublicData publicData)
        {
            throw new NotImplementedException();
        }

        abstract protected void DoProcess(InternalData internalData);

        public void Process(PublicData publicData)
        {
            InternalData internalData = CreateInternalDataFromPublicData(publicData);
            DoProcess(internalData);
        }
    }

    public sealed class Derived : Base
    {
        protected override void DoProcess(InternalData internalData)
        {
            throw new NotImplementedException();
        }
    }
Run Code Online (Sandbox Code Playgroud)

也就是说,Base包含一些内部逻辑,并不打算由我的程序集之外的类继承; 而Derived从外部访问. InternalData还包含一些内部逻辑,因为它(并且应该)永远不会从外部使用,我也希望将其内部化.

当然上面的代码不会编译,因为它Base不应该比它更容易访问Derived.我可以设置Basepublic,这很好,但它会导致另一个问题.如果Base是公开的,那么ExternalDerived : Base在其他组件中可能会有一些.但Base.DoProcess接受一个InternalData作为其参数,因此ExternalDerived无法实现它(因为它不知道InternalData).内部无参数Base构造函数阻止创建任何ExternalDerived实例,因此没有人会实现ExternalDerived.DoProcess,也不InternalData需要公开曝光,但编译器不知道它.

我如何重写上面的代码,以便有一个抽象的DoProcess(InternalData)方法,所以这个InternalData类将是内部的?

Ali*_*ice 12

从 C# 7.2 开始,存在private protected访问修饰符,这意味着“仅对同一程序集中的派生类可用”。

换句话说,它必须满足internalAND的条件protectedprotected internal这与internalOR不同protected

您可以将基类的构造函数标记为private protected,从而有效地防止通过程序集外部的此构造函数继承该类,同时仍然允许在该程序集(以及程序集的友元)内进行继承。

所以,像这样的类:

public abstract BaseClass
{
    private protected BaseClass() {}
}
Run Code Online (Sandbox Code Playgroud)

被有效地密封在程序集之外,同时仍然可以在程序集内继承。


mmd*_*bas 0

设置Basepublic.

public abstract class Base {...
Run Code Online (Sandbox Code Playgroud)

更改 Base.DoProcess:

protected virtual void DoProcess<T>(T internalData)
{
    if (!(internalData is InternalData))
    {
        throw new ArgumentOutOfRangeException("internalData");
    }
}
Run Code Online (Sandbox Code Playgroud)

更改 Derived.DoProcess:

protected override void DoProcess<T>(T internalData)
{
    base.DoProcess(internalData);
    // Other operations
}
Run Code Online (Sandbox Code Playgroud)