C# 设置程序集中所有类型都可访问的访问器,并仅获取派生类型的访问器。如何?

标签 c# properties protected internal accessor

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

class SomeType {
    private int length;
    internal int Length {
        get { return length; }
        set length = value; }
    }
}

允许 SomeType 程序集中的所有类型使用 getset 访问器。 问题:如何将对 set 的访问限制为从 SomeType(实际上是 SomeType)派生的类型?

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

被编译器拒绝,因为据说 protectedinternal 限制更少(假设: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 理论上可以被程序集外部的类型访问,但由于类是内部的,因此来自不同程序集的任何内容都不应从您的类型派生。

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

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

能够创建一个内部属性,如果 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/

相关文章:

c# - 使用 LINQ 拆分数组

c# - 在 C# 中获取 Selenium RemoteWebDriver 的 session ID

python - 关于如何在 python 中使用属性功能的真实示例?

iphone - iPhone 开发中的 Objective-C 属性

java - 一个子类的对象可以访问另一个子类的另一个对象的 protected 字段吗?

c# - Visual Studio 加载项。如何禁用菜单项

c# - 通过 TCP 读取嗅探数据

javascript - 比较 JavaScript 中的属性名称

php - 如何保护PHP中的类

c++ - C++17 中 protected 构造函数的规则改变了吗?