C# 设置访问器可访问程序集中的所有类型,而获取访问器仅可访问派生类型。怎样做?

发布于 2024-08-18 07:43:13 字数 1180 浏览 9 评论 0原文

具有无访问修饰符的类型中的此属性(因此是内部访问):

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

原谅过去的我 2024-08-25 07:43:13

(编辑:我刚刚检查过,即使属性的类型与声明类型相同,这也有效。但是,当您尝试声明属性时,它不起作用public 类型中,其中属性的类型是 internal 类型。)

在 C# 中你不能完全做到这一点(严格来说),但你可以做一些非常类似:(

protected internal int Length { get; protected set; }

这只是为了简单起见而使用自动实现的属性;相同的技术也适用于“普通”属性。)

这将使同一程序集中的任何类型都可以访问“getter” 派生类型; “setter”只能由派生类型访问。由于您的类无论如何都是内部的,所以这几乎是等效的 - 理论上,程序集外部的类型可以访问 getter,但由于该类是内部的,所以无论如何,来自不同程序集的任何内容都不应该从您的类型派生。

问题是属性要求一个访问级别是另一个访问级别的“子集”; internalprotected 的工作方式不同 - 一种类型可以位于同一程序集中,但不能从相关类型派生;可以从它派生出另一种类型,但在不同的程序集中。基本上它们是正交的。

上述解决方案之所以有效,是因为受保护的内部意味着它可以被同一程序集中或从该类型派生的任何类型访问。显然,protectedinternal 都是其中的一个子集。

如果 C# 具有与 CLR“系列程序集”等价的东西,您将能够创建一个内部属性,该属性对于setter受到进一步限制。访问级别。 (受保护的内部相当于“家族程序集”。)不幸的是,对你来说,它不是:(

如果你真的想要最初的规定的目标(例如,如果您以后有一个公共类,想要对其应用相同的限制),则必须将其中至少一个作为单独的方法,例如

private int length;
internal int Length { get { return length; } }

protected void SetLength(int value)
{
    this.length = value;
}

(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:

protected internal int Length { get; protected set; }

(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 and protected 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 of protected and internal 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.

private int length;
internal int Length { get { return length; } }

protected void SetLength(int value)
{
    this.length = value;
}
如痴如狂 2024-08-25 07:43:13

由于类本身仅在声明程序集中可见(由于隐式 internal 访问修饰符),因此只需将属性上的 getter 设置为 public 并将 setter 设置为 protected

class SomeType {
    private int length;

    public int Length {
        get { return length; }
        protected set { length = value; }
    }
}

吸气剂将无法在程序集外部访问,因为类本身不可见。


题外话:如果您有最新的 C# 编译器,您可能想改用自动属性:

class SomeType {
    public int Length { get; protected set; }
}

这只是一种语言/编译器技巧,因此您不必针对 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 property public and the setter protected:

class SomeType {
    private int length;

    public int Length {
        get { return length; }
        protected set { length = value; }
    }
}

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:

class SomeType {
    public int Length { get; protected set; }
}

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.

浴红衣 2024-08-25 07:43:13

你不能扭转它吗(没有测试过):

protected int Length
{
    internal get { return length; }
    set { length = value; }
}

Can't you turn it around (haven't tested it):

protected int Length
{
    internal get { return length; }
    set { length = value; }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文