0

プライベートクラスのサブクラスのユーザーがプライベートクラスのパブリックメンバーデータにアクセスできないのはなぜですか?以下は、コンパイルされないという点で、私には非常に直感に反しているようです。

public class OuterClassBase {
    private class PrivateInnerClass {
        public void DoSomething () {}
    }

    protected class ProtectedInnerClass : PrivateInnerClass {}
}


public class OuterClassDerived : OuterClassBase {
    public OuterClassDerived () {
        ProtectedInnerClass o = new ProtectedInnerClass();
        o.DoSomething(); // inaccessible due to its pretection level
    }
}

public PrivateInnerClass/ protectedにすると、コードをコンパイルできます...

4

3 に答える 3

3

C# 4 仕様のセクション 3.5 から:

メンバーの宣言により、メンバー アクセスを制御できます。メンバーのアクセシビリティは、メンバーの宣言されたアクセシビリティ (§3.5.1) と、すぐに含まれる型のアクセシビリティ (存在する場合) を組み合わせることによって確立されます。
...
アクセスが行われるテキストの場所がメンバーのアクセシビリティ ドメイン (§3.5.2) に含まれている場合、メンバーへのアクセスが許可されます。

次に、セクション 3.5.2 (アクセシビリティ ドメイン) で:

プログラム P 内の型 T で宣言されたネストされたメンバー M のアクセシビリティ ドメインは、次のように定義されます (M 自体が型である可能性があることに注意してください)。

  • M の宣言されたアクセシビリティがパブリックである場合、M のアクセシビリティ ドメインは T のアクセシビリティ ドメインです。
  • ...
  • M の宣言されたアクセシビリティが非公開の場合、M のアクセシビリティ ドメインは T のプログラム テキストです。

これはここに当てはまります。つまり、 のアクセシビリティ ドメインはDoSomething最初PrivateInnerClassの箇条書きの のアクセシビリティ ドメインです... しかし、最後の箇条書きPrivateInnerClassのプログラム テキストはのアクセシビリティ ドメインです。OuterClassBase

したがって、 内の呼び出しOuterClassDerivedはのアクセシビリティ ドメインにないDoSomethingため、呼び出すことができません。

そもそもProtectedInnerClass派生できることに本当に驚いています...PrivateInnerClass

編集:そして、できないことが判明しました...OuterClassDerivedクラスを完全に削除しても、次のエラーが発生します:

Test.cs(10,21): error CS0060: Inconsistent accessibility: base class
        'OuterClassBase.PrivateInnerClass' is less accessible than class
        'OuterClassBase.ProtectedInnerClass'

これは、仕様のセクション 10.1.4.1 に違反しています。

クラス型の直接の基本クラスは、少なくともクラス型自体と同じくらいアクセス可能でなければなりません (§3.5.2)。たとえば、パブリック クラスがプライベート クラスまたは内部クラスから派生すると、コンパイル時エラーになります。

ここでは、プライベート クラスから保護されたクラスを派生させようとしています。保護されたクラスはプライベート クラスよりもアクセスしやすいため、エラーが発生します。

于 2012-07-20T21:12:26.220 に答える
2

PrivateInnerClass は OuterClassBase に対してプライベートです。OuterClassBase 以外は使用できません (これがプライベートの意味です)。

サブクラス化してもルールは変更されませんが、それでもプライベートです。サブクラス化がプライベート制約を破り、OuterBaseClass の外部の誰かが PrivateInnerClass のメンバーにアクセスできるようにする場合、これは違法であり、コンパイルされません。

言い換えれば、何かがプライベートであるよりもプライベートであると宣言されている場合、プライベート宣言をバイパスできるようにするトリックはコンパイルしないでください (リフレクションを除く)。

于 2012-07-20T20:56:31.323 に答える
0

保護されたクラスは、パブリック クラスが内部クラスから継承できないのと同じ理由で、プライベート クラスから継承できません。クラスは、その基底クラスよりもアクセスしやすくすることはできません。

しかし、なぜあなたはこれをやろうとしていますか?他のクラスが PrivateInnerClass から直接継承しないようにすることができますが、それらが別のアセンブリにある場合に限ります。次のようなこともできます。フレームワークは、内部/パブリック クラスで多くのことを行います。

public class OuterClassBase
{
    private class PrivateInnerClass : ProtectedInnerClass
    {
    }

    protected abstract class ProtectedInnerClass
    {
        public void DoSomething() { }
    }

    protected ProtectedInnerClass ProtectedInnerClassFactoryMethod()
    {
        return new PrivateInnerClass();
    }
}

public class OuterClassDerived : OuterClassBase
{
    public OuterClassDerived()
    {
        ProtectedInnerClass o = ProtectedInnerClassFactoryMethod();
        o.DoSomething();
    }
} 
于 2012-07-20T21:32:03.443 に答える