此属性在具有无访问权限修饰符的类型中(因此是内部
访问权限):
class SomeType {
private int length;
internal int Length {
get { return length; }
set length = value; }
}
}
允许 SomeType 程序集中的所有类型使用 get
和 set
访问器。 问题:如何将对 set
的访问限制为仅从 SomeType(实际上是 SomeType)派生的类型?
internal int Length {
get { return length; }
protected set length = value; }
}
被编译器拒绝,因为据说 protected
比 internal
限制更少(假设:protected
有一个交集 与 internal
,但 不完全包含 internal
--> 派生类型可以存在于 internal 的范围之外
)。
什么代码可以被程序集中的任何类型访问,并且仅由程序集中的派生类型设置?
编辑:查看答案后,我认为我需要添加属性的另一个特征,因为它可能对解决方案产生影响:属性的类型实际上是 SomeType
。编辑后的代码是:
class SomeType {
private SomeType length;
internal SomeType Length {
get { return length; }
set length = value; }
}
}
如果属性声明为public
,则编译器会发出错误(属性类型 SomeType 比属性 Length 更难访问)。
最佳答案
(编辑:我刚刚检查过,即使属性的类型与声明类型相同,它也能工作。但是,当您尝试在 public 类型中声明属性,其中属性的类型是 internal 类型。)
在 C# 中你不能完全做到这一点(严格来说),但你可以做一些非常相似的事情:
protected internal int Length { get; protected set; }
(为了简单起见,这里使用自动实现的属性;同样的技术也适用于“普通”属性。)
这将使同一程序集和派生类型中的任何类型都可以访问“getter”; “setter”只能由派生类型访问。由于您的类无论如何都是内部的,因此这几乎是等价的 - setter/getter 理论上可以被程序集外部的类型访问,但由于类是内部的,因此来自不同程序集的任何内容都不应从您的类型派生。
问题是属性要求一个访问级别是另一个的“子集”; internal
和 protected
不是这样工作的——一种类型可以在同一个程序集中,但不是从相关类型派生的;可以从它派生出另一种类型,但在不同的程序集中。它们基本上是正交的。
上述解决方案之所以有效,是因为protected internal
意味着它可以被同一程序集中或从该类型派生的任何类型访问。。很明显,protected
和 internal
都是其中的一个子集。
您将能够创建一个内部
属性,如果 C# 有一些等同于 CLR“系列”的东西,则该属性对 setter 有进一步的限制和 程序集”访问级别。 (protected internal
等同于“family or assembly”。)不幸的是,它不是 :(
如果您真的想要最初设定的目标(例如,如果您以后有一个公共(public)类(class),您想要对其应用相同的限制),您必须至少将其中一个作为单独的目标方法,例如
private int length;
internal int Length { get { return length; } }
protected void SetLength(int value)
{
this.length = value;
}
关于C# 设置程序集中所有类型都可访问的访问器,并仅获取派生类型的访问器。如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2081255/