C#で、パブリック、プライベート、保護、アクセス修飾子なしの違いは何ですか?


728

すべての私の大学時代、私は使用しているpublic、との違いを知りたいのですがpublicprivateprotected

また、何もstaticないのとは対照的に何をしますか?

回答:


1008

アクセス修飾子

docs.microsoft.comから:

public

型またはメンバーには、同じアセンブリまたはそれを参照する別のアセンブリ内の他のコードからアクセスできます。

private

型またはメンバーには、同じクラスまたは構造体のコードからのみアクセスできます。

protected

型またはメンバーには、同じクラスまたは構造体のコード、または派生クラスでのみアクセスできます。

private protected (C#7.2で追加)

型またはメンバーには、同じクラスまたは構造体のコード、または同じアセンブリの派生クラスでのみアクセスできますが、別のアセンブリからはアクセスできません。

internal

タイプまたはメンバーには、同じアセンブリ内の任意のコードからアクセスできますが、別のアセンブリからはアクセスできません。

protected internal

型またはメンバーには、同じアセンブリ内の任意のコード、または別のアセンブリ内の派生クラスからアクセスできます。

アクセス修飾子が設定されていない場合、デフォルトのアクセス修飾子が使用されます。したがって、たとえ設定されていなくても、常に何らかの形のアクセス修飾子が存在します。

static 修飾子

クラスの静的修飾子は、クラスをインスタンス化できないこと、およびそのすべてのメンバーが静的であることを意味します。静的メンバーには、その包含タイプのインスタンスがいくつ作成されるかに関係なく、1つのバージョンがあります。

静的クラスは基本的に非静的クラスと同じですが、1つだけ違いがあります。静的クラスを外部でインスタンス化することはできません。つまり、newキーワードを使用してクラス型の変数を作成することはできません。インスタンス変数がないため、クラス名自体を使用して静的クラスのメンバーにアクセスします。

ただし、静的コンストラクタなどがあります。静的クラスを含め、どのクラスにもこれらのいずれかを含めることができます。それらを直接呼び出すことはできず、パラメーター(クラス自体の型パラメーター以外)を持つこともできません。最初のインスタンスが作成される前、または静的メンバーが参照される前に、静的コンストラクターが自動的に呼び出されてクラスを初期化します。このように見えます:

static class Foo()
{
    static Foo()
    {
        Bar = "fubar";
    }

    public static string Bar { get; set; }
}

静的クラスは多くの場合サービスとして使用され、次のように使用できます。

MyStaticClass.ServiceMethod(...);

17
そして、あなたは非静的クラスに静的メソッドを持つことができますよね?
ジョンブブリスキー

14
はい、私の例と同じように動作します。
mbillard 2009年

7
この文脈で「アセンブリ」という用語は何を意味しますか?
Jonathan Gleason

1
@gotoVoid Googleで検索したものはどれも誤りです。MSDNによると、保護された内部とは、「型またはメンバーは、宣言されているアセンブリ内の任意のコードから、または別のアセンブリの派生クラス内からアクセスできる」という意味です。
Kevin

2
ProtectedとPrivate Protectedの違いは何ですか?私には、どちらも同じように聞こえる..
goofyui

161

グラフィカルな概要(要約)

可視性

以来、静的クラスはシールされている保護されたキーワードは、静的クラスに無効であるので、彼らは、(Objectから除いて)継承することはできません。



アクセス修飾子を前に配置しない場合のデフォルトについては、C#のクラスとメンバー(フィールド、メソッドなど)のデフォルトの可視性を参照してください

ネストされていない

enum                              public
non-nested classes / structs      internal
interfaces                        internal
delegates in namespace            internal
class/struct member(s)            private
delegates nested in class/struct  private

ネスト:

nested enum      public
nested interface public
nested class     private
nested struct    private

また、それらは密封されたキーワードがあり、クラスを継承不可能にします。
また、VB.NETではキーワードが異なる場合があるため、ここにチートシートがあります。

VBとCSの同等物


1
@ᴀʀᴜnBᴇrtiL:よろしいですか?別のアセンブリの派生クラスですか?
Stefan Steiger、2015年

同じアセンブリ内の派生クラス、同じアセンブリ内ではできません。同じアセンブリ内のようにあなたが意味するものだと思いました...
Arun Bertil

1
@ᴀʀᴜnBᴇrtiL:うーん、そうですね、これは実際にはハッチングされているはずです。
Stefan Steiger 2015

1
図に誤りがあると思います。クラスにinternalが使用されている場合、そのクラスは同じアセンブリ内の別のクラスによって派生できます。また、内部修飾子がプロパティで使用されている場合、このプロパティは同じアセンブリの派生クラスでもアクセスできます。おそらく、「を含むアセンブリ」の下に「はい」があるため図は正しいですが、「派生クラス」の下に「いいえ」があるため、誤解される可能性があります。
AH。

160

Public-クラスを見ることができれば、メソッドを見ることができます

プライベート - クラスの一部である場合、メソッドを表示できます。それ以外の場合は表示されません。

保護 -プライベートと同じですが、すべての子孫もメソッドを見ることができます。

静的(クラス) -「クラス」と「オブジェクト」の違いを覚えていますか?すべてを忘れてください。それらは「静的」と同じです...クラスはそれ自体の唯一のインスタンスです。

静的(メソッド) -このメソッドを使用するときはいつでも、それが属しているクラスの実際のインスタンスとは独立した参照フレームがあります。


1
非静的クラスに静的メソッドを含めることはできませんか?
ジョンブブリスキー

1
はい、しかし私は静的クラスについて話していました。静的メソッドを説明する別のエントリを追加しました。キャッチありがとうございます。
JosephStyons 2009年

2
すべてのクラスの基本型はSystem.Objectであるため、C#について語る場合、 'オブジェクト'はここでは適切な用語ではない可能性があります。「インスタンス」はより適切な単語、または「オブジェクト」(小文字の「O」)になります。
lesderid 2012

@lesderid 'object'は 'System.Object'のエイリアスです。これを使用すると混乱する可能性があります。「インスタンス」のほうがいいと思います:)
dpp

同じ規則が構造体に適用されます。
gsharp 14

35

この回答から素晴らしい図を再投稿します

ベン図のすべてのアクセス修飾子を、より限定的なものからより無差別なものまで、以下に示します。

private
ここに画像の説明を入力してください

private protected-C#7.2で追加
ここに画像の説明を入力してください

internal
ここに画像の説明を入力してください

protected
ここに画像の説明を入力してください

protected internal
ここに画像の説明を入力してください

public
ここに画像の説明を入力してください


24

ここに画像の説明を入力してください

using System;

namespace ClassLibrary1
{
    public class SameAssemblyBaseClass
    {
        public string publicVariable = "public";
        protected string protectedVariable = "protected";
        protected internal string protected_InternalVariable = "protected internal";
        internal string internalVariable = "internal";
        private string privateVariable = "private";
        public void test()
        {
            // OK
            Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(publicVariable);

            // OK
            Console.WriteLine(protectedVariable);

            // OK
            Console.WriteLine(internalVariable);

            // OK
            Console.WriteLine(protected_InternalVariable);
        }
    }

    public class SameAssemblyDerivedClass : SameAssemblyBaseClass
    {
        public void test()
        {
            SameAssemblyDerivedClass p = new SameAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }

    public class SameAssemblyDifferentClass
    {
        public SameAssemblyDifferentClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // NOT OK
            // Console.WriteLine(privateVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            //Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }
}

 using System;
        using ClassLibrary1;
        namespace ConsoleApplication4

{
    class DifferentAssemblyClass
    {
        public DifferentAssemblyClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            // Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protectedVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protected_InternalVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protected_InternalVariable);
        }
    }

    class DifferentAssemblyDerivedClass : SameAssemblyBaseClass
    {
        static void Main(string[] args)
        {
            DifferentAssemblyDerivedClass p = new DifferentAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            //Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);

            SameAssemblyDerivedClass dd = new SameAssemblyDerivedClass();
            dd.test();
        }
    }
}

1
この回答が過去5年間の他の多くの回答に何を追加するのかわかりません。
John Saunders

4
これは単なる説明です。他の回答は少し混乱し、半分は回答した
ので

4
@John Saunders:派生クラスの可視性を、同じクラスにあるクラスと別のアセンブリにあるクラスとで区別することで区別されます。さらに、サンプルコードを表示することで、その情報にどのように到達したかを説明します。したがって、実際には他の回答に追加されます。彼のネクロマンシングはおそらく私の回答のコメントによって引き起こされたのでしょう。
Stefan Steiger

2
「異なるアセンブリの派生クラス」-これは、別の回答ですでに与えられているチャートに価値を追加します。違いは、特に「保護された内部」の場合に役立ちます
Nirman

このチャートは、私が理解するのが最も簡単だと思います。これを(C#7.2で)維持するにPrivate Protectedは、を追加するには、同じクラス= Yes、同じアセンブリ、派生クラス= Yes、同じアセンブリ、任意のクラス= NO、異なるアセンブリ、派生クラス= NO、異なるアセンブリ、任意のクラス=になりNOます。もう1つの提案はprotected internal、の単語の順序を入れ替えないことです。これにより、肺炎を@ user1810087の回答から切り離します
Intrastellar Explorer

22

の質問について

  • 名前空間タイプはデフォルトで内部です
  • ネストされた型を含むすべての型メンバーは、デフォルトでプライベートです

15

現在のアクセス修飾子のさらに別の視覚的アプローチ(C#7.2)。スキーマがそれをより簡単に思い出すのに役立つことを願っています
(対話型ビューの画像をクリックしてください)。

インタラクティブアクセス修飾子svg

外側内側

2ワードのアクセス修飾子を覚えるのに苦労している場合は、outside-insideを覚えておいてください

  • プライベート保護プライベート 外部(同じアセンブリ)内部で保護 (同じアセンブリ)
  • 保護内部外部保護 (同じアセンブリ)内部内部(同じアセンブリ)

11

うーん。

ここを参照してください: アクセス修飾子

手短に:

publicは、メソッドまたはタイプに他のタイプ/クラスからの完全な可視性を提供します。

Privateは、プライベートメソッド/変数へのアクセスをプライベートメソッド/変数に含むタイプのみを許可します(ネストされたクラスは、含まれるクラスプライベートメソッド/変数へのアクセスも持つことに注意してください)。

Protectedは、派生クラスも保護されたメソッドにアクセスできることを除いて、privateに似ています。

「なし」はVB.NETのnullに相当します。「何も」が「アクセス修飾子なし」を意味している場合、それは場合によって異なりますが、大まかな経験則(確かにC#で)は、アクセス修飾子を明示的に指定しない場合、メソッド/変数宣言は通常、可能な限り制限されています。すなわち

public class MyClass
{
    string s = "";
}

実質的には次と同じです:

public class MyClass
{
    private string s = "";
}

リンクされたMSDNの記事は、明示的に指定されたアクセス修飾子がない場合の完全な説明を提供します。


8

国民は -誰のどこかによるアクセスすることができます。
private-所属するクラス内からのみアクセスできます。
protected-クラスまたはクラスから継承するオブジェクト内からのみアクセスできます。

nullのようなものはありませんが、VB内です。
静的とは、そのオブジェクトのインスタンスが1つあり、そのクラスのインスタンスごとにメソッドがあることを意味します。


4

うーん...

静的とは、クラスのインスタンスがなくてもその関数にアクセスできることを意味します。

クラス定義から直接アクセスできます。


4

Privateのステータスは、変数が同じクラスのオブジェクトによってのみアクセスできることを示します。保護ステータスは、そのアクセスを拡張して、クラスの子孫も含めるようにします。

「上記の表から、プライベートと保護の違いを確認できます。両方が同じであると思います...それで、この2つの別々のコマンドの必要性とは」

詳細については、MSDNリンクを確認してください


3

これらのアクセス修飾子は、メンバーが表示される場所を指定します。あなたはおそらくこれを読むべきです。IainMHによって提供されたリンクを開始点として使用します。

静的メンバーはクラスごとに1つであり、インスタンスごとに1つではありません。


3

クラスのアクセシビリティに注意してください。パブリッククラスと保護クラスおよびメソッドには、デフォルトで誰でもアクセスできます。

また、Microsoftは、Visual Studioで新しいクラスが作成されたときに、アクセス修飾子(public、protectedなどのキーワード)を表示することについてはそれほど明確ではありません。したがって、クラスのアクセシビリティについては十分に注意して検討してください。これは、実装の内部への扉です。


2

それは良いOOPデザインに関係していると思います。ライブラリの開発者であれば、ライブラリの内部の仕組みを隠したいでしょう。そうすれば、後でライブラリの内部の仕組みを変更できます。そのため、メンバーとヘルパーメソッドをプライベートとして配置し、インターフェイスメソッドのみをパブリックにします。上書きする必要があるメソッドは保護する必要があります。


1

C#には、合計6つのアクセス修飾子があります。

private:このアクセシビリティを使用して宣言されたメンバーは、包含型内で表示できます。派生型、同じアセンブリ内の他の型、または包含アセンブリ外の型には表示されません。つまり、アクセスは包含タイプのみに制限されます。

protected:このアクセシビリティで宣言されたメンバーは、包含アセンブリ内の包含型から派生した型、および包含アセンブリ外の包含型から派生した型内で表示できます。つまり、アクセスは包含型の派生型に制限されます。

internal:このアクセシビリティで宣言されたメンバーは、このメンバーを含むアセンブリ内で表示できますが、それを含むアセンブリの外部のアセンブリからは表示できません。つまり、アクセスは、含まれているアセンブリのみに制限されます。

internal protected:このアクセシビリティーで宣言されたメンバーは、包含アセンブリー内または外の包含タイプから派生したタイプ内で表示できます。また、包含アセンブリ内のすべてのタイプからも表示できます。つまり、アクセスは、アセンブリまたは派生型を含むことに限定されます。

public:このアクセシビリティで宣言されたメンバーは、このメンバーを含むアセンブリ、またはそれを含むアセンブリを参照する他のアセンブリ内で表示できます。つまり、アクセスは制限されません。

C#7.2では、新しいレベルのアクセシビリティが追加されています。

private protected:このアクセシビリティーで宣言されたメンバーは、包含アセンブリー内のこの包含タイプから派生したタイプ内で表示できます。含まれているタイプから派生していないタイプ、または含まれているアセンブリの外部には表示されません。つまり、アクセスは包含アセンブリ内の派生型に制限されます。

新しいプライベート保護アクセス修飾子のサンプルコードを含むソース


0

C#のすべてのアクセス修飾子の説明

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.