如何在 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
,但只允许它由派生类设置。 我尝试将 Headers
设置为内部,但 protected 并不比内部更具限制性。 有没有办法使标头成为内部及其设置访问器受保护和内部?
我觉得我严重滥用了访问修饰符,因此任何设计帮助将不胜感激。
Here is my shortened abstract class:
abstract class Report {
protected internal abstract string[] Headers { get; protected set; }
}
Here is a derived class:
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;
}
}
The idea is, I want to be able to call Report.Headers
from anywhere in the assembly, but only allow it to be set by derived classes. I tried making Headers
just internal, but protected does not count as more restrictive than internal. Is there a way to make Headers internal and its set accessor protected AND internal?
I feel like I'm grossly misusing access modifiers, so any design help would be greatly appreciate.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这在 C# 中是不可能的。
只是为了完整性,IL(族和程序集访问修饰符)支持这一点。
It's not possible in C#.
Just for the sake of completeness, this is supported in IL (family and assembly access modifier).
将 getter 公开有什么问题吗? 如果您声明该属性,因为
它满足您想要的所有条件:程序集的所有成员都可以获取该属性,并且只有派生类可以设置它。 当然,程序集外部的类也可以获得该属性。 所以?
如果您确实需要在程序集中公开该属性,但不是公开的,另一种方法是创建一个不同的属性:
当然,用
I_
前缀装饰名称是很丑陋的。 但这是一个奇怪的设计。 对内部属性进行某种名称修改是提醒自己(或其他开发人员)他们使用的属性是非正统的一种方式。 另外,如果您后来决定像这样的混合可访问性并不是真正解决您的问题的正确解决方案,您将知道要修复哪些属性。What's wrong with making the getter public? If you declare the property as
it meets all of the criteria you want: all members of the assembly can get the property, and only derived classes can set it. Sure, classes outside the assembly can get the property too. So?
If you genuinely need to expose the property within your assembly but not publicly, another way to do it is to create a different property:
Sure, it's ugly decorating the name with that
I_
prefix. But it's kind of a weird design. Doing some kind of name mangling on the internal property is a way of reminding yourself (or other developers) that the property they're using is unorthodox. Also, if you later decide that mixing accessibility like this is not really the right solution to your problem, you'll know which properties to fix.我会将访问修饰符保持为受保护状态,并有一个内部辅助方法。
但不知怎的,这听起来像是应该以某种方式重构。 内部始终是我很少使用的东西,因为它可能会导致非常混乱的体系结构,其中所有内容都以某种方式使用程序集中的其他所有内容,但当然总有例外。
I would keep the access modifier as protected and have an internal helper method.
But somehow, this smells like it should be refactored somehow. Internal is always something I'd use sparingly because it can lead to a very messy architecture where everything is somehow using everything else within the assembly, but of course there's always exceptions.
您可以使用内部显式实现的接口:
现在您可以在定义 IReport 的程序集中获得内部访问权限,这应该正是您想要的。
显式实现接口并不是一种众所周知的策略,但它解决了很多问题。
You could use an internal explicit implemented Interface:
Now you get internal access in the assembly where IReport is defined, which should be exactly what you want.
Implementing interfaces explicitly isn't a well known strategy, but it solves alot of problems.
从 C# 7.2 开始,有构造
private protected
(链接)。 它不允许从现场读取(因此并不完全符合OP的意图),但值得抢夺。Since C# 7.2 there is construct
private protected
(link). It does not allow reading from the field (thus does not do exactly what the OP intends), but worth taking a loot.CLR 支持受保护的 AND 内部的概念(称为族和程序集可访问性),并且 C# 应该实现/公开此概念。 C# 可能应该允许以下操作:
这样做应该对属性设置器的两个可见性修饰符进行 INTERSECT/AND 操作,并允许您从同一程序集中的任何位置读取标头,但只能从同一程序集中的派生类设置它。
The CLR supports the concept of protected AND internal (known as family-and-assembly accessibility) and C# SHOULD implemented/expose this concept. C# should probably allow the following:
Doing so should INTERSECT/AND both visibility modifiers for the property setter and allow you to read Headers from anywhere within the same assembly but only set it from derived classes within the same assembly.
人们普遍认为,您不能让某些成员既受到保护又处于内部。
确实,你不能像包括我自己在内的许多人所希望的那样,用一行代码来做到这一点,但只要有一些聪明才智,它是 100% 可行的。
It's a common belief that you cannot make some members both protected AND internal.
And its true that you cannot do so in a single line, as many, including myself, would wish, but with some cleverness it is 100% do-able.
不是完美的优雅,但一个可行的解决方案,明确地实现它:
SetHeader只能由派生类访问,除非_allowSetHeader设置为true,否则它将什么也不做,这只能由内部类完成...
Not perfectly elegant but a workable solution, implement it explicitly :
SetHeader can only be accessed by a derived class and it will do nothing unless _allowSetHeader is set true which can only be done by an internal class...