C# 设置访问器可访问程序集中的所有类型,而获取访问器仅可访问派生类型。怎样做?
具有无访问修饰符的类型中的此属性(因此是内部
访问):
class SomeType {
private int length;
internal int Length {
get { return length; }
set length = value; }
}
}
允许 SomeType 程序集中的所有类型使用 get
和 设置
访问器。 问题:如何将对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 相比不易访问)。
This property in a type with no access modifier (thus internal
access):
class SomeType {
private int length;
internal int Length {
get { return length; }
set length = value; }
}
}
allows all types within the assembly of SomeType to use get
and set
accessors. Problem: how to restrict the access to set
to only types derived from SomeType (and SomeType indeed)?
internal int Length {
get { return length; }
protected set length = value; }
}
is rejected by the compiler, because protected
is said to be less restrictive than internal
(supposedly: protected
has an intersection with internal
, but is not entirely included in internal
--> Derived types can exist beyond the scope of internal
).
What would be the code to have get accessed by any type within the assembly, and set only by derivated types within the assembly?
Edit: after reviewing the answers, I think I need to add another characteristic of the property, since it may make a difference in the solution: the type of the property is actually SomeType
. The edited code is:
class SomeType {
private SomeType length;
internal SomeType Length {
get { return length; }
set length = value; }
}
}
If the property is declared public
, then the compiler issues an error (the property type SomeType is less accessible the property Length).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
(编辑:我刚刚检查过,即使属性的类型与声明类型相同,这也有效。但是,当您尝试声明属性时,它不起作用在 public 类型中,其中属性的类型是 internal 类型。)
在 C# 中你不能完全做到这一点(严格来说),但你可以做一些非常类似:(
这只是为了简单起见而使用自动实现的属性;相同的技术也适用于“普通”属性。)
这将使同一程序集中的任何类型都可以访问“getter”和 派生类型; “setter”只能由派生类型访问。由于您的类无论如何都是内部的,所以这几乎是等效的 - 理论上,程序集外部的类型可以访问 getter,但由于该类是内部的,所以无论如何,来自不同程序集的任何内容都不应该从您的类型派生。
问题是属性要求一个访问级别是另一个访问级别的“子集”;
internal
和protected
的工作方式不同 - 一种类型可以位于同一程序集中,但不能从相关类型派生;可以从它派生出另一种类型,但在不同的程序集中。基本上它们是正交的。上述解决方案之所以有效,是因为
受保护的内部
意味着它可以被同一程序集中或从该类型派生的任何类型访问。显然,protected
和internal
都是其中的一个子集。如果 C# 具有与 CLR“系列和程序集”等价的东西,您将能够创建一个
内部
属性,该属性对于setter受到进一步限制。访问级别。 (受保护的内部
相当于“家族或程序集”。)不幸的是,对你来说,它不是:(如果你真的想要最初的规定的目标(例如,如果您以后有一个公共类,想要对其应用相同的限制),则必须将其中至少一个作为单独的方法,例如
(EDIT: I've just checked, and this works even when the type of the property is the same as the declaring type. However, it doesn't work when you're trying to declare a property within a public type where the type of the property is an internal type.)
You can't quite do that in C# (strictly speaking), but you can do something very similar:
(This is using an automatically implemented property just for simplicity; the same technique would work for a "normal" property too.)
This will make the "getter" accessible to any type within the same assembly and derived types; the "setter" will only be accessible to derived types. As your class is internal anyway, this is pretty much equivalent anyway - the getter would theoretically be accessible to types outside the assembly, but as the class is internal, nothing from a different assembly should be deriving from your type anyway.
The problem is that properties require that one access level is a "subset" of the other;
internal
andprotected
don't work like that - one type can be in the same assembly but not derived from the type in question; another type can be derived from it but in a different assembly. They're orthogonal, basically.The above solution works because
protected internal
means it's accessible to any type which is either in the same assembly or derived from the type. Clearly each ofprotected
andinternal
individually is a subset of this.You would be able to make an
internal
property which was further restricted for the setter if C# had some equivalent to the CLR "family and assembly" access level. (protected internal
is equivalent to "family or assembly".) Unfortunately for you, it doesn't :(If you really want the originally stated goals (e.g. if you later have a public class you want to apply the same restrictions to), you'll have to make at least one of them a separate method instead, e.g.
由于类本身仅在声明程序集中可见(由于隐式
internal
访问修饰符),因此只需将属性上的 getter 设置为public
并将 setter 设置为protected
:吸气剂将无法在程序集外部访问,因为类本身不可见。
题外话:如果您有最新的 C# 编译器,您可能想改用自动属性:
这只是一种语言/编译器技巧,因此您不必针对 3.X 版本框架进行编译即可使用它。
Since the class itself is only visible in the declaring assembly (due to the implicit
internal
access modifier), just make the getter on the propertypublic
and the setterprotected
:The getter will not be accessible out outside of your assembly, since the class itself is not visible.
Off topic: if you have a recent C# compiler, you might want to use auto properties instead:
This is a language/compiler trick only, so you do not have to compile against a version 3.X framework to make use of it.
你不能扭转它吗(没有测试过):
Can't you turn it around (haven't tested it):