C #에서 public, private, protected 및 access modifier가없는 차이점은 무엇입니까?


728

내가 가진 내 모든 대학 년 사용하고 public,와의 차이를 알고 싶습니다 public, private그리고 protected?

또한 static아무것도없는 것과는 반대로 무엇을 하는가?

답변:


1007

액세스 수정 자

에서 docs.microsoft.com :

public

형식이나 멤버는 동일한 어셈블리 또는 다른 어셈블리를 참조하는 다른 코드로 액세스 할 수 있습니다.

private

유형 또는 멤버는 동일한 클래스 또는 구조체의 코드로만 액세스 할 수 있습니다.

protected

유형 또는 멤버는 동일한 클래스 또는 구조체 또는 파생 클래스의 코드로만 액세스 할 수 있습니다.

private protected (C # 7.2에 추가됨)

유형 또는 멤버는 동일한 클래스 또는 구조체의 코드 또는 동일한 어셈블리의 파생 클래스에서만 액세스 할 수 있지만 다른 어셈블리에서는 액세스 할 수 없습니다.

internal

유형이나 멤버는 동일한 어셈블리의 코드로 액세스 할 수 있지만 다른 어셈블리에서는 액세스 할 수 없습니다.

protected internal

유형 또는 멤버는 동일한 어셈블리의 코드 또는 다른 어셈블리의 파생 클래스를 통해 액세스 할 수 있습니다.

접근 수정이 설정되어 있지 않은, 기본 액세스 수정이 사용됩니다. 따라서 설정되지 않은 경우에도 항상 일부 형식의 액세스 수정자가 있습니다.

static 수정 자

클래스의 정적 수정자는 클래스를 인스턴스화 할 수없고 모든 멤버가 정적임을 의미합니다. 정적 멤버는 작성 유형의 인스턴스 수에 관계없이 하나의 버전을 갖습니다.

정적 클래스는 기본적으로 비 정적 클래스와 동일하지만 한 가지 차이점이 있습니다. 정적 클래스는 외부에서 인스턴스화 할 수 없습니다. 즉, new 키워드를 사용하여 클래스 유형의 변수를 작성할 수 없습니다. 인스턴스 변수가 없으므로 클래스 이름 자체를 사용하여 정적 클래스의 멤버에 액세스합니다.

그러나 정적 생성자 와 같은 것이 있습니다. 정적 클래스를 포함하여 모든 클래스는 이들 중 하나를 가질 수 있습니다. 직접 호출 할 수 없으며 클래스 자체의 유형 매개 변수 이외의 매개 변수를 가질 수 없습니다. 첫 번째 인스턴스가 작성되거나 정적 멤버가 참조되기 전에 클래스를 초기화하기 위해 정적 생성자가 자동으로 호출됩니다. 다음과 같습니다 :

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

    public static string Bar { get; set; }
}

정적 클래스는 종종 서비스로 사용되므로 다음과 같이 사용할 수 있습니다.

MyStaticClass.ServiceMethod(...);

17
그리고 비 정적 클래스에서 정적 메소드를 가질 수 있습니다.
John Bubriski

14
예, 그들은 내 예와 같은 방식으로 행동합니다.
mbillard

7
이 문맥에서 "조립"이라는 용어는 무엇을 의미합니까?
Jonathan Gleason

1
@gotoVoid Google에서 검색 한 내용이 잘못되었습니다. MSDN 에 따르면 , protected internal은 "유형이나 멤버가 선언 된 어셈블리의 코드 또는 다른 어셈블리의 파생 클래스 내에서 형식이나 멤버에 액세스 할 수 있습니다"라는 의미입니다.
Kevin

2
보호 및 개인 보호의 차이점은 무엇입니까? 나를 위해, 그것은 .. 모두 동일한 소리
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
@ ᴀʀᴜn BᴇrtiL : 확실합니까? 다른 어셈블리의 파생 클래스?
Stefan Steiger

같은 어셈블리에서 파생 된 클래스, 우리는 할 수 없습니다. 나는 당신이 같은 어셈블리에서와 같은 줄 알았는데 ...
Arun Bertil

1
@ ᴀʀᴜn BᴇrtiL : 흠, 이것은 실제로 부화되어야합니다.
Stefan Steiger

1
다이어그램에 오류가 있다고 생각합니다. internal이 클래스에 사용되는 경우 동일한 어셈블리의 다른 클래스에서 클래스를 파생시킬 수 있습니다. 또한 내부 수정자가 속성에서 사용되는 경우 동일한 어셈블리의 파생 클래스에서이 속성에 액세스 할 수도 있습니다. "어셈블리 포함"아래에 "예"가 있기 때문에 다이어그램이 올바른 것일 수도 있지만 "파생 클래스"아래에 "아니오"가 있기 때문에 잘못 이해 될 수 있습니다.
.

160

공개 -클래스를 볼 수 있다면 메소드를 볼 수 있습니다

비공개 - 클래스의 일부인 경우 메소드를 볼 수 있습니다. 그렇지 않으면 그렇지 않습니다.

보호됨 -개인과 동일하며 모든 자손 도 방법을 볼 수 있습니다.

정적 (클래스) - "클래스"와 "오브젝트"의 차이점을 기억하십니까? 다 잊어 버려 그것들은 "정적"과 동일합니다 ... 클래스는 그 자체의 유일한 인스턴스입니다.

정적 (메소드) -이 메소드를 사용할 때마다 해당 클래스의 실제 인스턴스에 관계없이 참조 프레임이 생깁니다.


1
정적이 아닌 클래스에 정적 메소드를 가질 수 없습니까?
John Bubriski

1
예, 그러나 정적 클래스에 대해 이야기하고있었습니다. 정적 메소드를 설명하기 위해 별도의 항목을 추가했습니다. 캐치 주셔서 감사합니다.
JosephStyons

2
모든 클래스의 기본 유형은 System.Object 이므로 C #에 대해 이야기 할 때 'Object'는 여기서 좋은 용어가 아닐 수 있습니다 . '인스턴스'는 더 나은 단어이거나 '개체'(소문자 'O')입니다.
lesderid

@lesderid 'object'는 'System.Object'의 별칭이므로 혼동 될 수 있습니다. '인스턴스'가 더 좋을 것 같습니다.)
dpp

구조체에도 동일한 규칙이 적용됩니다.
gsharp

35

이 답변 에서 멋진 다이어그램을 다시 게시하십시오 .

Venn 다이어그램의 모든 액세스 수정자는 제한에서 무차별까지입니다.

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
이것은 간단한 설명 일뿐입니다. 다른 답변은 조금 혼란 반 : 대답됨에
Narottam 고얄을

4
@ John Saunders : 파생 클래스에 대한 가시성을 동일한 클래스에있는 클래스와 다른 어셈블리에있는 클래스간에 구분하여 차별화합니다. 또한 샘플 코드를 표시하여 해당 정보를 얻는 방법을 제공합니다. 따라서 실제로 다른 답변에 추가됩니다. 그의 대답은 아마도 내 대답에 대한 나의 의견에 의해 촉발되었을 것입니다.
Stefan Steiger

2
"다른 어셈블리의 파생 클래스"-다른 답변에 이미 제공된 차트에 값을 추가합니다. 차이는 특히 "내부 보호"의 경우에 유용합니다
Nirman

이 차트가 이해하기 가장 쉬운 것으로 나타났습니다. 이 현재 (C # 7.2 사용)를 유지하려면을 추가하십시오 Private Protected: 동일한 클래스 = Yes, 동일한 어셈블리, 파생 클래스 = Yes, 동일한 어셈블리, 모든 클래스 = NO, 다른 어셈블리, 파생 클래스 = NO, 다른 어셈블리, 모든 클래스 = NO. protected internal@ user1810087의 답변에서 폐음을 깰 수 있기 때문에에 대한 단어 순서를 바꾸지 않는 한 가지 추가 제안도 있습니다.
Intrastellar Explorer

22

Nothing 의 문제에 대하여

  • 네임 스페이스 유형은 기본적으로 내부입니다.
  • 중첩 유형을 포함한 모든 유형 멤버는 기본적으로 비공개입니다.

15

현재 액세스 수정 자의 또 다른 시각적 접근 방식 (C # 7.2). 스키마가 더 쉽게 기억하는 데 도움이되기를 바랍니다
(대화식보기를 위해 이미지를 클릭하십시오).

대화식 액세스 수정 자 svg

외부 내부

두 단어로 된 액세스 수정자를 기억하기 어려우면 outside-inside를 기억하십시오 .

  • 개인 보호 : 개인 외부 (동일한 어셈블리) 내부 (동일한 어셈블리) 보호
  • 내부 보호 : 보호 외측 (동일한 어셈블리) 내부의 내부 (동일한 어셈블리)

11

흠.

액세스 수정 자를 참조하십시오 .

간단히 말해서 :

Public은 다른 유형 / 클래스에서 메소드 또는 유형을 완전히 볼 수있게합니다.

Private은 private 메서드 / 변수를 포함하는 형식 만 private 메서드 / 변수에 액세스 할 수 있습니다 (중첩 클래스도 포함하는 클래스 private 메서드 / 변수에 액세스 할 수 있음).

Protected는 파생 클래스가 보호 된 메서드에 액세스 할 수 있다는 점을 제외하면 private과 유사합니다.

"Nothing"은 VB.NET의 null과 같습니다. "액세스 수정 자 없음"을 의미하는 "아무것도 없음"을 언급하고 있지만, 매우 거친 경험 법칙 (확실히 C #)은 액세스 수정자를 명시 적으로 지정하지 않으면 메소드 / 변수 선언은 일반적으로 가능한 한 제한적 입니다. 즉

public class MyClass
{
    string s = "";
}

사실상 다음과 같습니다.

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

링크 된 MSDN 기사는 명시 적으로 지정된 액세스 수정자가 없을 때 자세한 설명을 제공합니다.


8

공개 -어디서나 누구나 액세스 할 수 있습니다.
private- 클래스에 속한 클래스에서만 액세스 할 수 있습니다.
protected- 클래스 또는 클래스에서 상속되는 모든 객체에서만 액세스 할 수 있습니다.

VB에서는 null과 같은 것은 없습니다.
정적은 해당 객체의 인스턴스 하나, 해당 클래스의 모든 인스턴스에 대한 메소드가 있음을 의미합니다.


4

음 ...

정적은 클래스의 인스턴스가 없어도 해당 함수에 액세스 할 수 있음을 의미합니다.

클래스 정의에서 직접 액세스 할 수 있습니다.


4

Private 상태는 변수가 동일한 클래스의 객체에 의해서만 액세스 될 수 있음을 나타냅니다. 보호 상태는 해당 클래스의 하위 항목도 포함하도록 해당 액세스를 확장합니다.

"위의 표에서 우리는 개인과 보호 된 것의 차이를 볼 수 있습니다. 둘 다 동일하다고 생각합니다 .... 따라서 두 개의 별도 명령이 필요합니다."

자세한 내용은 MSDN 링크 확인


3

이러한 액세스 수정자는 멤버가 표시되는 위치를 지정합니다. 아마 이것을 읽어야 할 것입니다. IainMH가 제공 한 링크를 출발점으로 삼으십시오.

정적 멤버는 클래스 당 하나이며 인스턴스 당 하나가 아닙니다.


3

수업에 대한 접근성을주의 깊게 살펴보십시오. 공개 및 보호 클래스 및 메소드는 기본적으로 모든 사람이 액세스 할 수 있습니다.

또한 Microsoft는 Visual Studio에서 새 클래스를 만들 때 액세스 수정 자 (공개, 보호 등 키워드)를 표시하는 데 그다지 익숙하지 않습니다. 따라서 클래스의 접근성에 대해 신중하게 생각하고 구현 내부에 문의하십시오.


2

좋은 OOP 디자인과 관련이 있다고 생각합니다. 라이브러리 개발자 인 경우 라이브러리의 내부 작업을 숨기려고합니다. 이렇게하면 나중에 라이브러리 내부 작업을 수정할 수 있습니다. 따라서 멤버 및 도우미 메소드를 개인용으로 지정하고 인터페이스 메소드 만 공용입니다. 덮어 써야하는 방법은 보호해야합니다.


1

C #에는 총 6 개의 액세스 수정자가 있습니다.

private :이 액세스 가능성으로 선언 된 멤버는 포함 유형 내에서 볼 수 있으며 파생 된 유형, 동일한 어셈블리의 다른 유형 또는 포함 된 어셈블리 외부의 유형에는 표시되지 않습니다. 즉, 액세스는 포함 유형으로 만 제한됩니다.

protected :이 액세스 가능성으로 선언 된 멤버는 포함 어셈블리 내의 포함 유형에서 파생 된 유형과 포함 어셈블리 외부의 포함 유형에서 파생 된 유형 내에서 볼 수 있습니다. 즉, 액세스는 포함 유형의 파생 유형으로 제한됩니다.

internal :이 내게 필요한 옵션으로 선언 된 멤버는이 멤버를 포함하는 어셈블리 내에서 볼 수 있지만 포함하는 어셈블리 외부의 모든 어셈블리에서는 볼 수 없습니다. 즉, 액세스는 어셈블리 만 포함하도록 제한됩니다.

내부 보호됨 :이 액세스 가능성으로 선언 된 멤버는 포함 어셈블리 내부 또는 외부의 포함 유형에서 파생 된 유형 내에서 볼 수 있으며 포함 어셈블리 내의 모든 유형에서도 볼 수 있습니다. 즉, 액세스는 어셈블리 또는 파생 형식을 포함하는 것으로 제한됩니다.

public :이 액세스 가능성으로 선언 된 멤버는이 멤버를 포함하는 어셈블리 또는 포함하는 어셈블리를 참조하는 다른 어셈블리에서 볼 수 있습니다. 즉, 액세스가 제한되지 않습니다.

C # 7.2는 새로운 수준의 접근성을 추가하고 있습니다.

private protected :이 액세스 가능성으로 선언 된 멤버는 포함하는 어셈블리 내에서이 포함 형식에서 파생 된 형식 내에서 볼 수 있습니다. 포함 유형 또는 포함 어셈블리 외부에서 파생되지 않은 유형에는 표시되지 않습니다. 즉, 액세스는 포함 어셈블리 내에서 파생 된 유형으로 제한됩니다.

새로운 개인 보호 액세스 수정 자의 샘플 코드를 포함한 소스


0

C #에 대한 모든 액세스 수정 자 설명

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.