답변:
에서 docs.microsoft.com :
형식이나 멤버는 동일한 어셈블리 또는 다른 어셈블리를 참조하는 다른 코드로 액세스 할 수 있습니다.
유형 또는 멤버는 동일한 클래스 또는 구조체의 코드로만 액세스 할 수 있습니다.
유형 또는 멤버는 동일한 클래스 또는 구조체 또는 파생 클래스의 코드로만 액세스 할 수 있습니다.
private protected
(C # 7.2에 추가됨)유형 또는 멤버는 동일한 클래스 또는 구조체의 코드 또는 동일한 어셈블리의 파생 클래스에서만 액세스 할 수 있지만 다른 어셈블리에서는 액세스 할 수 없습니다.
유형이나 멤버는 동일한 어셈블리의 코드로 액세스 할 수 있지만 다른 어셈블리에서는 액세스 할 수 없습니다.
유형 또는 멤버는 동일한 어셈블리의 코드 또는 다른 어셈블리의 파생 클래스를 통해 액세스 할 수 있습니다.
때 접근 수정이 설정되어 있지 않은, 기본 액세스 수정이 사용됩니다. 따라서 설정되지 않은 경우에도 항상 일부 형식의 액세스 수정자가 있습니다.
static
수정 자클래스의 정적 수정자는 클래스를 인스턴스화 할 수없고 모든 멤버가 정적임을 의미합니다. 정적 멤버는 작성 유형의 인스턴스 수에 관계없이 하나의 버전을 갖습니다.
정적 클래스는 기본적으로 비 정적 클래스와 동일하지만 한 가지 차이점이 있습니다. 정적 클래스는 외부에서 인스턴스화 할 수 없습니다. 즉, new 키워드를 사용하여 클래스 유형의 변수를 작성할 수 없습니다. 인스턴스 변수가 없으므로 클래스 이름 자체를 사용하여 정적 클래스의 멤버에 액세스합니다.
그러나 정적 생성자 와 같은 것이 있습니다. 정적 클래스를 포함하여 모든 클래스는 이들 중 하나를 가질 수 있습니다. 직접 호출 할 수 없으며 클래스 자체의 유형 매개 변수 이외의 매개 변수를 가질 수 없습니다. 첫 번째 인스턴스가 작성되거나 정적 멤버가 참조되기 전에 클래스를 초기화하기 위해 정적 생성자가 자동으로 호출됩니다. 다음과 같습니다 :
static class Foo()
{
static Foo()
{
Bar = "fubar";
}
public static string Bar { get; set; }
}
정적 클래스는 종종 서비스로 사용되므로 다음과 같이 사용할 수 있습니다.
MyStaticClass.ServiceMethod(...);
그래픽 개요 (간단히 요약)
이후 정적 클래스가 밀봉되어 보호 키워드는 정적 클래스에 유효하므로, 그들은 (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에서는 키워드가 때때로 다르므로 여기에 치트 시트가 있습니다.
공개 -클래스를 볼 수 있다면 메소드를 볼 수 있습니다
비공개 - 클래스의 일부인 경우 메소드를 볼 수 있습니다. 그렇지 않으면 그렇지 않습니다.
보호됨 -개인과 동일하며 모든 자손 도 방법을 볼 수 있습니다.
정적 (클래스) - "클래스"와 "오브젝트"의 차이점을 기억하십니까? 다 잊어 버려 그것들은 "정적"과 동일합니다 ... 클래스는 그 자체의 유일한 인스턴스입니다.
정적 (메소드) -이 메소드를 사용할 때마다 해당 클래스의 실제 인스턴스에 관계없이 참조 프레임이 생깁니다.
이 답변 에서 멋진 다이어그램을 다시 게시하십시오 .
Venn 다이어그램의 모든 액세스 수정자는 제한에서 무차별까지입니다.
private
:
private protected
: -C # 7.2에 추가됨
internal
:
protected
:
protected internal
:
public
:
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();
}
}
}
Private Protected
: 동일한 클래스 = Yes
, 동일한 어셈블리, 파생 클래스 = Yes
, 동일한 어셈블리, 모든 클래스 = NO
, 다른 어셈블리, 파생 클래스 = NO
, 다른 어셈블리, 모든 클래스 = NO
. protected internal
@ user1810087의 답변에서 폐음을 깰 수 있기 때문에에 대한 단어 순서를 바꾸지 않는 한 가지 추가 제안도 있습니다.
현재 액세스 수정 자의 또 다른 시각적 접근 방식 (C # 7.2). 스키마가 더 쉽게 기억하는 데 도움이되기를 바랍니다
(대화식보기를 위해 이미지를 클릭하십시오).
두 단어로 된 액세스 수정자를 기억하기 어려우면 outside-inside를 기억하십시오 .
흠.
액세스 수정 자를 참조하십시오 .
간단히 말해서 :
Public은 다른 유형 / 클래스에서 메소드 또는 유형을 완전히 볼 수있게합니다.
Private은 private 메서드 / 변수를 포함하는 형식 만 private 메서드 / 변수에 액세스 할 수 있습니다 (중첩 클래스도 포함하는 클래스 private 메서드 / 변수에 액세스 할 수 있음).
Protected는 파생 클래스가 보호 된 메서드에 액세스 할 수 있다는 점을 제외하면 private과 유사합니다.
"Nothing"은 VB.NET의 null과 같습니다. "액세스 수정 자 없음"을 의미하는 "아무것도 없음"을 언급하고 있지만, 매우 거친 경험 법칙 (확실히 C #)은 액세스 수정자를 명시 적으로 지정하지 않으면 메소드 / 변수 선언은 일반적으로 가능한 한 제한적 입니다. 즉
public class MyClass
{
string s = "";
}
사실상 다음과 같습니다.
public class MyClass
{
private string s = "";
}
링크 된 MSDN 기사는 명시 적으로 지정된 액세스 수정자가 없을 때 자세한 설명을 제공합니다.
이러한 액세스 수정자는 멤버가 표시되는 위치를 지정합니다. 아마 이것을 읽어야 할 것입니다. IainMH가 제공 한 링크를 출발점으로 삼으십시오.
정적 멤버는 클래스 당 하나이며 인스턴스 당 하나가 아닙니다.
좋은 OOP 디자인과 관련이 있다고 생각합니다. 라이브러리 개발자 인 경우 라이브러리의 내부 작업을 숨기려고합니다. 이렇게하면 나중에 라이브러리 내부 작업을 수정할 수 있습니다. 따라서 멤버 및 도우미 메소드를 개인용으로 지정하고 인터페이스 메소드 만 공용입니다. 덮어 써야하는 방법은 보호해야합니다.
C #에는 총 6 개의 액세스 수정자가 있습니다.
private :이 액세스 가능성으로 선언 된 멤버는 포함 유형 내에서 볼 수 있으며 파생 된 유형, 동일한 어셈블리의 다른 유형 또는 포함 된 어셈블리 외부의 유형에는 표시되지 않습니다. 즉, 액세스는 포함 유형으로 만 제한됩니다.
protected :이 액세스 가능성으로 선언 된 멤버는 포함 어셈블리 내의 포함 유형에서 파생 된 유형과 포함 어셈블리 외부의 포함 유형에서 파생 된 유형 내에서 볼 수 있습니다. 즉, 액세스는 포함 유형의 파생 유형으로 제한됩니다.
internal :이 내게 필요한 옵션으로 선언 된 멤버는이 멤버를 포함하는 어셈블리 내에서 볼 수 있지만 포함하는 어셈블리 외부의 모든 어셈블리에서는 볼 수 없습니다. 즉, 액세스는 어셈블리 만 포함하도록 제한됩니다.
내부 보호됨 :이 액세스 가능성으로 선언 된 멤버는 포함 어셈블리 내부 또는 외부의 포함 유형에서 파생 된 유형 내에서 볼 수 있으며 포함 어셈블리 내의 모든 유형에서도 볼 수 있습니다. 즉, 액세스는 어셈블리 또는 파생 형식을 포함하는 것으로 제한됩니다.
public :이 액세스 가능성으로 선언 된 멤버는이 멤버를 포함하는 어셈블리 또는 포함하는 어셈블리를 참조하는 다른 어셈블리에서 볼 수 있습니다. 즉, 액세스가 제한되지 않습니다.
C # 7.2는 새로운 수준의 접근성을 추가하고 있습니다.
private protected :이 액세스 가능성으로 선언 된 멤버는 포함하는 어셈블리 내에서이 포함 형식에서 파생 된 형식 내에서 볼 수 있습니다. 포함 유형 또는 포함 어셈블리 외부에서 파생되지 않은 유형에는 표시되지 않습니다. 즉, 액세스는 포함 어셈블리 내에서 파생 된 유형으로 제한됩니다.