web-dev-qa-db-ja.com

(C#7.2)「private protected」修飾子の使用例は何ですか?

C#7.2では、private protected修飾子 が導入されています。

私は常にプロパティを持つフィールドへのアクセスを保護し、通常はオブジェクトの内部状態を自分のクラス以外によって変更したくないため、Get/Setメソッドを介したアクセスを許可しています。

C#言語チームがこの機能を追加した理由を理解しようとしています。グーグルで大規模な検索を行い、「新機能」メディアを読んで見た後( プレスリリースdetails and videos by Mads Torgerson )、私はまだ賢明ではありません。

私には、これにより開発者がLiskov Substitutionの原則を破ることができるように見えますが、これは、この機能がなぜ存在するのか理解していないためかもしれません。

なぜではなく、それがどのように使用できるかを理解しています-誰かがMSDNドキュメントで考案されたものではなく、実際の使用例を提供できますか?

62
Jay

C#7.2より前は、protected internal修飾子がありました。これは本当に保護されていることを意味しますOR internal、つまり-メンバーAは、そのクラスがクラスの子ではない場合でも、現在のアセンブリ内の任意のクラスからもアクセスできます。 A(「保護」によって暗示される制限が緩和されます)。

private protectedは、保護された内部を意味します。つまり、メンバーは同じアセンブリにある子クラスにのみアクセスできますが、アセンブリの外にある子クラスにはアクセスできません(「保護」によって暗示される制限がさらに制限されます)。これは、アセンブリでクラスの階層を構築し、他のアセンブリの子クラスがその階層の特定の部分にアクセスしないようにする場合に役立ちます。

Jon Skeet 提供 コメント の例を挙げることができます。クラスがあるとします

public class MyClass {

}

また、現在のアセンブリでのみ継承できるようにしたいが、このクラス階層内からの場合を除き、このクラスを直接インスタンス化できるようにしたくない。

内部コンストラクターを使用して、現在のアセンブリ内でのみ継承することができます

public class MyClass {
    internal MyClass() {
    }
}

保護されたコンストラクターを使用すると、現在のクラス階層を使用しない限り、直接インスタンス化を防止できます。

public class MyClass {
    protected MyClass() {
    }
}

両方を取得するには、private protectedコンストラクタが必要です。

public class MyClass {
    private protected MyClass() {
    }
}
59
Evk

パブリック抽象基本クラスの実装の一部として使用するSomeHelperという内部クラスがあると仮定します。

_public abstract class Test
{
    // Won't compile because SomeHelper is internal.
    protected SomeHelper CreateHelper()
    {
        return new SomeHelper();
    }

    public int Func(int x)
    {
        var helper = CreateHelper();
        return helper.DoSomething(x);
    }
}

internal class SomeHelper
{
    public virtual int DoSomething(int x)
    {
        return -x;
    }
}
_

内部型を返すprotectedメソッドを使用できないため、これはコンパイルされません。唯一の手段は、SomeHelperをそのように使用しないか、SomeHelperをパブリックにすることです。

SomeHelperTestの保護された内部クラスにすることはできますが、SomeHelperがベースから派生しない他のクラスで使用することを意図している場合は機能しませんクラス。)

_private protected_機能の導入により、次のようにCreateHelper()を宣言できます。

_private protected SomeHelper CreateHelper()
{
    return new SomeHelper();
}
_

これでコンパイルされ、内部を公開する必要がなくなります。

8
Matthew Watson

two-Wordアクセス修飾子の場合、私はこの概念を持っています-最初のアクセサーは別のアセンブリに関連し、2番目はそれが定義されたアセンブリに関連しています。

保護された内部

  • protected別のアセンブリ:子クラスでのみアクセス可能。

  • internal現在のアセンブリ内:現在のアセンブリ内の全員がアクセス可能。

プライベート保護

  • private別のアセンブリ:アクセスできません。
  • protected現在のアセンブリ:子クラスでのみアクセス可能。
8
Suren Srapyan