如何在C#中保护属性和内部?

xof*_*ofz 28 c# access-modifiers

这是我缩短的抽象类:

abstract class Report {

    protected internal abstract string[] Headers { get; protected set; }
}
Run Code Online (Sandbox Code Playgroud)

这是一个派生类:

class OnlineStatusReport : Report {

    static string[] headers = new string[] {
        "Time",
        "Message"
    }

    protected internal override string[] Headers {
        get { return headers; }
        protected set { headers = value; }
    }

    internal OnlineStatusReport() {
        Headers = headers;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的想法是,我希望能够Report.Headers从程序集中的任何地方调用,但只允许它由派生类设置.我尝试Headers只做内部,但受保护不算比内部更严格.有没有办法使Headers内部及其set访问器受到保护和内部?

我觉得我非常滥用访问修饰符,所以任何设计帮助都会非常感激.

Meh*_*ari 31

这在C#中是不可能的.

仅仅为了完整性,IL(系列和程序集访问修饰符)支持这一点.


Rob*_*ney 16

将吸气剂公之于众有什么问题?如果您将该属性声明为

public string[] Headers { get; protected set; }
Run Code Online (Sandbox Code Playgroud)

它符合您想要的所有条件:程序集的所有成员都可以获取属性,只有派生类可以设置它.当然,集会外的课程也可以获得房产.所以?

如果您确实需要在程序集中公开属性但不公开,则另一种方法是创建不同的属性:

protected string[] Headers { get; set; }
internal string[] I_Headers { get { return Headers; } }
Run Code Online (Sandbox Code Playgroud)

当然,用这个I_前缀装饰名字很难看.但这是一种奇怪的设计.在内部属性上进行某种名称修改是一种提醒自己(或其他开发人员)他们正在使用的属性是非正统的方式.此外,如果您稍后决定这样的混合可访问性不是您的问题的正确解决方案,您将知道要修复哪些属性.

  • 它只有在`protected`属性的类型是`public`时才有效,比如`string []`.如果`protected`属性的类型本身是`internal` - 编译失败,消息"不一致的可访问性:属性类型'Library.A'不像属性'Library.OnlineStatusReport.Headers'` (3认同)

Mic*_*tum 6

我会将访问修饰符保持为受保护并具有内部帮助方法.

protected override string[] Headers {
    get { return headers; } // Note that get is protected
    set { headers = value; }
}

internal SetHeadersInternal(string[] newHeaders)
{
    headers = newHeaders;
}
Run Code Online (Sandbox Code Playgroud)

但不知何故,这闻起来应该以某种方式重构.内部总是我谨慎使用的东西,因为它可能导致一个非常混乱的架构,其中一切都以某种方式使用组件中的其他东西,但当然总是例外.


Lun*_*ynx 6

您可以使用内部显式实现的接口:

internal interface IReport
{
    string[] Headers { get; }
}

abstract class Report : IReport
{
    protected abstract string[] Headers { get; protected set; }

    string[] IReport.Headers
    {
        get { return Headers; }
    }
}

class OnlineStatusReport : Report
{
    static string[] headers = new string[] { "Time", "Message" };

    protected internal override string[] Headers
    {
        get { return headers; }
        protected set { headers = value; }
    }

    internal OnlineStatusReport()
    {
        Headers = headers;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以在定义了IReport的程序集中获得内部访问权限,这应该是您想要的.

明确地实现接口不是一个众所周知的策略,但它解决了很多问题.


Dar*_*ker 5

由于 C# 7.2 有构造private protected链接)。它不允许从现场读取(因此不完全符合 OP 的意图),但值得一试。