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

C#设置可访问程序集中所有类型的访问器,并仅对派生类型获取评估器。如何?,c#,properties,protected,internal,accessor,C#,Properties,Protected,Internal,Accessor,此属性位于带有无访问权限修饰符的类型中(因此内部访问权限): 允许SomeType程序集中的所有类型使用get和set访问器问题:如何将对集的访问限制为仅从SomeType派生的类型(实际上是SomeType) 被编译器拒绝,因为protected被认为比internal(假定:受保护的与内部有一个交集,但是未完全包含在内部-->派生类型可以超出内部的范围) 什么代码可以被程序集中的任何类型访问,并且只能由程序集中的派生类型设置 编辑:查看答案后,我认为需要添加属性的另一个特征,因为它可能会对解

此属性位于带有无访问权限修饰符的类型中(因此
内部访问权限):

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

被编译器拒绝,因为
protected
被认为比
internal
(假定:
受保护的
内部
有一个交集,但是未完全包含在
内部
-->派生类型可以超出
内部
的范围)

什么代码可以被程序集中的任何类型访问,并且只能由程序集中的派生类型设置

编辑:查看答案后,我认为需要添加属性的另一个特征,因为它可能会对解决方案产生影响:属性的类型实际上是
SomeType
。编辑的代码是:

class SomeType {
    private SomeType length;
    internal SomeType Length {
        get { return length; }
        set length = value; }
    }
}
如果属性被声明为
public
,则编译器会发出一个错误(属性类型SomeType的可访问性低于属性长度)。

您不能将其转过来(尚未测试它):

(编辑:我刚刚检查过,即使属性的类型与声明类型相同,此操作也有效。但是,当您试图在公共类型中声明属性,而该属性的类型是内部类型时,此操作不起作用。)

在C#(严格地说)中你不能做到这一点,但你可以做一些非常类似的事情:

protected internal int Length { get; protected set; }
(这只是为了简单起见而使用自动实现的属性;同样的技术也适用于“普通”属性。)

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

问题是属性要求一个访问级别是另一个的“子集”;
internal
protected
不是这样工作的-一个类型可以在同一个程序集中,但不能从所讨论的类型派生;另一个类型可以从它派生,但在不同的程序集中。它们基本上是正交的

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

如果C#具有与CLR“系列和程序集”访问级别相当的访问级别,您将能够创建一个
内部
属性,该属性对setter进行了进一步限制。(
受保护的内部
相当于“系列或程序集”。)不幸的是,它没有:(

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

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

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

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

class SomeType {
    private int length;

    public int Length {
        get { return length; }
        protected set { length = value; }
    }
}
由于类本身不可见,因此在程序集外部无法访问getter


离题:如果您有一个最新的C#编译器,您可能希望改用自动属性:

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

这只是一种语言/编译器技巧,因此您不必针对3.X版框架进行编译来使用它。

内部
的限制性并不比
受保护的
强,因此我认为这是不合法的。我猜我们需要分别查看类的访问和属性的访问。通过设置对public属性的访问,我们可以使用protected for get。但是由于类是内部的,所以只有从SomeType派生的对象,并且已经可以访问SomeType(因此在同一程序集中)可以访问集合访问器。但这对我来说还不够清楚…请重试编辑的代码。您可以毫无问题地将该属性设置为公共属性,并使setter受到保护。您只是不能在引用内部类型的公共类型中创建这样的属性。Jon,这是正确的。在这一点上,我有点困惑,因为我无法重新设置把最初的问题复杂化。我实际上是从一个依赖属性的包装开始的。这个包装有问题。最后,你和其他人提出的很多建议都有效。所以,在这个时候,我将这些答案标记为肯定的。谢谢各位,我欣赏了你们的评论。你们不必为了让我们满意而根据3.X框架进行编译e自动实现的属性-您只需使用C#3或C#4编译器。您仍然可以将目标锁定(即针对).NET 2.0。好吧,我认为这会起作用。但是,我的案例还有另一个在我提供的简化代码示例中看不到的特征:实际上属性的类型不是int,而是SomeType本身。在类型为内部时将属性公开会隐式导致编译器抱怨t的类型属性的可访问性不如属性。实际上,这是我的headach开始的地方…@Mike:这就是为什么给出有代表性的示例很重要的原因…我将编辑我的答案。@Mike:事实上,我刚刚尝试过,这个解决方案仍然有效。如果您试图声明一个属性,它只会给出内部可访问性错误
private int length;
internal int Length { get { return length; } }

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

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