如何在C#中保护属性并使其内部化?

这是我缩短的抽象类:

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

这是一个派生类:

 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; } } 

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

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

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

 public string[] Headers { get; protected set; } 

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

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

 protected string[] Headers { get; set; } internal string[] I_Headers { get { return Headers; } } 

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

这在C#中是不可能的。

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

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

 protected override string[] Headers { get { return headers; } // Note that get is protected set { headers = value; } } internal SetHeadersInternal(string[] newHeaders) { headers = newHeaders; } 

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

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

 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; } } 

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

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

CLR支持受保护的AND内部概念(称为系列和程序集可访问性),C#应该实现/公开这个概念。 C#应该允许以下内容:

 internal string[] Header { get; protected set; } 

这样做应该INTERSECT / AND属性设置器的两个可见性修饰符,并允许您从同一个程序集中的任何位置读取Headers,但只能从同一程序集中的派生类设置它。

人们普遍认为,你不能让一些成员受到保护和内部成员。

事实上,你不可能在一条线上这样做,正如许多人,包括我自己所希望的那样,但有一些聪明才能100%做到。

 //Code below is 100% tested /* FROM ProtectedAndInternal.dll */ namespace ProtectedAndInternal { public class MyServiceImplementationBase { protected static class RelevantStrings { internal static string AppName = "Kickin' Code"; internal static string AppAuthor = "Scott Youngblut"; } } public class MyServiceImplementation : MyServiceImplementationBase { public void PrintProperties() { // WORKS PERFECTLY BECAUSE SAME ASSEMBLY! Console.WriteLine(RelevantStrings.AppAuthor); } } public class NotMyServiceImplementation { public void PrintProperties() { // FAILS - NOT THE CORRECT INHERITANCE CHAIN // Error CS0122: 'ProtectedAndInternal.MyServiceImplementationBase.Relevant' is inaccessible due to its protection level // Console.WriteLine(MyServiceImplementationBase.RelevantStrings.AppAuthor); } } } /* From AlternateAssemblyService.dll which references ProtectedAndInternal.dll */ namespace AlternateAssemblyService { public class MyServiceImplementation : MyServiceImplementationBase { public void PrintProperties() { // FAILS - NOT THE CORRECT ASSEMBLY // Error CS0117: 'ProtectedAndInternal.MyServiceImplementationBase.RelevantStrings' does not contain a definition for 'AppAuthor' // Console.WriteLine(RelevantStrings.AppAuthor); } } } 

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