internal
C # 에서 키워드 의 실제 사용법이 무엇인지 설명해 주 시겠습니까?
것을 나는 알고 internal
현재 어셈블리에 대한 수정 액세스를 제한,하지만 나는 그것을 언제 어떤 상황에서 사용해야합니까?
internal
C # 에서 키워드 의 실제 사용법이 무엇인지 설명해 주 시겠습니까?
것을 나는 알고 internal
현재 어셈블리에 대한 수정 액세스를 제한,하지만 나는 그것을 언제 어떤 상황에서 사용해야합니까?
답변:
동일한 어셈블리 내의 다른 많은 클래스에서 액세스하려고하지만 다른 어셈블리의 코드에 액세스 할 수 없도록하려는 유틸리티 또는 도우미 클래스 / 방법.
에서 MSDN (archive.org를 통해) :
내부 액세스의 일반적인 사용은 구성 요소 기반 개발에 있으며, 이는 구성 요소 그룹이 나머지 응용 프로그램 코드에 노출되지 않고 개인 방식으로 협력 할 수 있기 때문입니다. 예를 들어, 그래픽 사용자 인터페이스를 구축하기위한 프레임 워크는 내부 액세스 권한이있는 멤버를 사용하여 협력하는 Control 및 Form 클래스를 제공 할 수 있습니다. 이러한 멤버는 내부에 있으므로 프레임 워크를 사용하는 코드에 노출되지 않습니다.
InternalsVisibleTo
어셈블리 레벨 속성 과 함께 내부 수정자를 사용 하여 대상 어셈블리 내부 클래스에 대한 특별 액세스 권한이 부여 된 "친구"어셈블리를 작성할 수도 있습니다.
이는 유닛 테스트 어셈블리를 생성 한 다음 테스트 할 어셈블리의 내부 멤버를 호출 할 수 있도록하는 데 유용 할 수 있습니다. 물론 다른 어셈블리에는이 수준의 액세스 권한이 부여되지 않으므로 시스템을 해제하면 캡슐화가 유지됩니다.
Bob이 BigImportantClass를 필요로하는 경우 Bob은 프로젝트 A를 소유 한 사람들이 가입하여 BigImportantClass가 자신의 요구를 충족하도록 작성되고, 그의 요구를 충족하는지 테스트하고, 그의 요구를 충족시키는 것으로 문서화되고, 프로세스임을 확인하도록해야합니다. 더 이상 그의 필요를 충족시키기 위해 변경되지 않도록하기 위해
클래스가 내부 클래스 인 경우 해당 프로세스를 거치지 않아도되므로 프로젝트 A의 예산을 절약하여 다른 것에 소비 할 수 있습니다.
내부의 요점은 그것이 밥에게 삶을 어렵게한다는 것이 아닙니다. 프로젝트 A가 기능, 수명, 호환성 등에 대해 비싼 약속을 제어 할 수 있습니다.
internal을 사용해야하는 또 다른 이유는 바이너리를 난독 처리하는 것입니다. obfuscator는 내부 클래스의 클래스 이름을 스크램블하는 것이 안전하지만 공개 클래스의 이름은 기존 참조를 손상시킬 수 있으므로 스크램블 할 수 없다는 것을 알고 있습니다.
많은 복잡한 기능을 간단한 공개 API로 캡슐화하는 DLL을 작성하는 경우 공개적으로 노출되지 않는 클래스 멤버에는 "내부"가 사용됩니다.
복잡성 숨기기 (일명 캡슐화)는 품질 소프트웨어 엔지니어링의 주요 개념입니다.
"엄격한 수정 자로 사용"규칙에 따라 구동되므로 다른 어셈블리에서 명시 적으로 액세스해야 할 때까지 다른 클래스의 메소드에 액세스해야하는 모든 곳에서 내부를 사용합니다.
어셈블리 인터페이스는 일반적으로 클래스 인터페이스의 합보다 좁기 때문에 사용하는 곳이 많이 있습니다.
내부가 많이 남용되는 것을 알았습니다. 당신은 실제로 다른 소비자에게 제공하지 않을 특정 클래스에만 특정 기능을 노출해서는 안됩니다.
제 생각에는 인터페이스가 깨지고 추상화가 깨집니다. 이것은 절대 사용해서는 안된다는 것이 아니라 더 나은 해결책은 다른 클래스로 리팩토링하거나 가능한 경우 다른 방식으로 사용하는 것입니다. 그러나 이것이 항상 가능한 것은 아닙니다.
문제가 발생할 수있는 이유는 다른 개발자가 귀하와 동일한 어셈블리에 다른 클래스를 작성해야 할 책임이 있기 때문입니다. 내부가 있으면 추상화의 선명도가 떨어지고 잘못 사용되면 문제가 발생할 수 있습니다. 공개 한 것과 같은 문제입니다. 다른 개발자가 작성하는 다른 클래스는 여전히 외부 클래스와 마찬가지로 소비자입니다. 클래스 추상화와 캡슐화는 외부 클래스를 보호하기위한 것이 아니라 모든 클래스를 보호하기위한 것입니다.
또 다른 문제는 많은 개발자들이 당시 어셈블리가 필요하지 않더라도 어셈블리의 다른 곳에서 사용하고 내부로 표시해야 할 수도 있다고 생각 한다는 것 입니다. 그런 다음 다른 개발자가 가지고 갈 것이라고 생각할 수 있습니다. 일반적으로 결정이 필요할 때까지 비공개로 표시하려고합니다.
그러나이 중 일부는 주관적 일 수 있으며 절대 사용해서는 안된다는 말은 아닙니다. 필요할 때만 사용하십시오.
내가 기억할 수없는 블로그에서 다른 날, 아마 일주일 동안 흥미로운 것을 보았습니다. 기본적으로 나는 이것을 인정 할 수는 없지만 유용한 응용 프로그램이있을 것이라고 생각했습니다.
다른 어셈블리에서 추상 클래스를 볼 수 있지만 다른 클래스에서 상속받을 수는 없다고 가정하십시오. 봉인은 이유 때문에 추상적이기 때문에 작동하지 않습니다. 해당 어셈블리의 다른 클래스는 상속합니다. 다른 어셈블리의 어딘가에 Parent 클래스를 선언하려는 경우 Private이 작동하지 않습니다.
네임 스페이스 Base.Assembly { 공공 추상 클래스 부모 { 내부 추상 void SomeMethod (); } // 이것은 동일한 어셈블리에 있기 때문에 제대로 작동합니다. 공개 클래스 ChildWithin : 부모 { 내부 재정의 void SomeMethod () { } } } 네임 스페이스 Another.Assembly { // 내부 메소드를 재정의 할 수 없기 때문에 Kaaboom 공개 클래스 ChildOutside : 부모 { } 공공 수업 시험 { // 그냥 괜찮아 개인 부모 _parent; 공개 테스트 () { // 아직 괜찮아 _parent = new ChildWithin (); } } }
보시다시피, 누군가 상속하지 않고도 Parent 클래스를 효과적으로 사용할 수 있습니다.
이 예에는 Assembly1.cs 및 Assembly2.cs라는 두 개의 파일이 있습니다. 첫 번째 파일에는 내부 기본 클래스 인 BaseClass가 있습니다. 두 번째 파일에서 BaseClass를 인스턴스화하려고하면 오류가 발생합니다.
// Assembly1.cs
// compile with: /target:library
internal class BaseClass
{
public static int intM = 0;
}
// Assembly1_a.cs
// compile with: /reference:Assembly1.dll
class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // CS0122
}
}
이 예제에서는 예제 1에서 사용한 것과 동일한 파일을 사용하고 BaseClass의 액세스 가능성 레벨을 public으로 변경하십시오 . 또한 멤버 IntM의 액세스 가능성 레벨을 internal로 변경하십시오 . 이 경우 클래스를 인스턴스화 할 수 있지만 내부 멤버에 액세스 할 수 없습니다.
// Assembly2.cs
// compile with: /target:library
public class BaseClass
{
internal static int intM = 0;
}
// Assembly2_a.cs
// compile with: /reference:Assembly1.dll
public class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // Ok.
BaseClass.intM = 444; // CS0117
}
}
출처 : http://msdn.microsoft.com/en-us/library/7c5ka91b(VS.80).aspx
내부 멤버가 선언 된 어셈블리로만 제한되는 내부의 매우 흥미로운 사용은 어느 정도 "친구"기능을 얻는 것입니다. 친구 구성원은 선언 된 어셈블리 외부의 특정 다른 어셈블리에서만 볼 수있는 것입니다. C #은 친구를 기본적으로 지원하지 않지만 CLR은 지원합니다.
InternalsVisibleToAttribute 를 사용 하여 친구 어셈블리를 선언 할 수 있으며 친구 어셈블리 내의 모든 참조는 선언 어셈블리의 내부 구성원을 친구 어셈블리 범위 내에서 공용으로 취급합니다. 이것의 문제점은 모든 내부 구성원이 보인다는 것입니다. 당신은 선택하고 선택할 수 없습니다.
InternalsVisibleTo의 유용한 용도는 다양한 내부 멤버를 단위 테스트 어셈블리에 노출시켜 해당 멤버를 테스트하기 위해 복잡한 리플렉션 작업을 수행 할 필요가 없다는 것입니다. 보이는 모든 내부 멤버는 그다지 큰 문제는 아니지만이 방법을 사용하면 클래스 인터페이스가 상당히 무거워지고 선언 어셈블리 내에서 캡슐화를 망칠 수 있습니다.
내부 클래스를 사용하면 어셈블리의 API를 제한 할 수 있습니다. API를 이해하기 쉽게 만드는 것과 같은 이점이 있습니다.
또한 어셈블리에 버그가 있으면 수정 사항이 변경 될 가능성이 적습니다. 내부 클래스가 없으면 클래스의 공개 멤버를 변경하는 것이 주요 변경 사항이라고 가정해야합니다. 내부 클래스를 사용하면 공용 멤버를 수정하면 어셈블리 (및 InternalsVisibleTo 특성에서 참조되는 어셈블리)의 내부 API 만 중단한다고 가정 할 수 있습니다.
클래스 수준과 어셈블리 수준에서 캡슐화를 좋아합니다. 이에 동의하지 않는 사람들도 있지만, 기능을 사용할 수 있다는 것을 아는 것이 좋습니다.
데이터 백엔드에 LINQ-to-SQL을 사용하는 프로젝트가 있습니다. Biz와 Data라는 두 가지 주요 네임 스페이스가 있습니다. LINQ 데이터 모델은 데이터에 있으며 "내부"로 표시됩니다. Biz 네임 스페이스에는 LINQ 데이터 클래스를 둘러싼 공개 클래스가 있습니다.
따라서 Data.Client
, Biz.Client
; 후자는 데이터 객체의 모든 관련 속성을 노출합니다. 예 :
private Data.Client _client;
public int Id { get { return _client.Id; } set { _client.Id = value; } }
Biz 객체에는 팩토리 메소드를 강제로 사용하는 개인 생성자와 다음과 같은 내부 생성자가 있습니다.
internal Client(Data.Client client) {
this._client = client;
}
라이브러리의 모든 비즈니스 클래스에서 사용할 수 있지만 프론트 엔드 (UI)는 데이터 모델에 직접 액세스 할 수 없으므로 비즈니스 계층이 항상 중개자 역할을합니다.
이것은 내가 실제로 internal
많이 사용한 첫 번째이며, 매우 유용하다는 것을 증명합니다.
클래스 멤버를 만드는 것이 합리적 일 수 있습니다 internal
. 클래스의 인스턴스화 방법을 제어하려는 경우를 예로들 수 있습니다. 클래스의 인스턴스를 만들기 위해 일종의 팩토리를 제공한다고 가정 해 봅시다. internal
동일한 어셈블리에있는 팩토리가 클래스의 인스턴스를 만들 수는 있지만 해당 어셈블리 외부의 코드 는 만들 수 없도록 constructor 를 만들 수 있습니다.
그러나 클래스 나 멤버 internal
를 특별한 이유없이 또는 클래스를 만드는 것이 의미가 없는 한 public
또는 private
특별한 이유없이 만드는 것은 아무 의미가 없습니다.
어떻습니까? 일반적으로 List 개체를 어셈블리의 외부 사용자에게 노출시키지 말고 IEnumerable을 노출시키는 것이 좋습니다. 그러나 배열 구문과 다른 모든 List 메서드를 가져 오기 때문에 어셈블리 내에서 List 개체를 사용하는 것이 훨씬 쉽습니다. 따라서 일반적으로 어셈블리 내부에서 사용할 List를 노출하는 내부 속성이 있습니다.
이 접근법에 대한 의견을 환영합니다.
public
누군가 정의한 클래스 는 프로젝트 네임 스페이스를 볼 때 인텔리전스에 자동으로 표시됩니다. API 관점에서는 프로젝트 사용자에게 사용 가능한 클래스 만 표시하는 것이 중요합니다. 사용internal
보이지 않는 것을 숨기려면 키워드를 하십시오.
귀하 Big_Important_Class
의 프로젝트 A가 프로젝트 외부에서 사용되도록 의도 된 경우이를 표시해서는 안됩니다 internal
.
그러나 많은 프로젝트에는 종종 프로젝트 내에서만 사용하도록 고안된 클래스가 있습니다. 예를 들어, 매개 변수화 된 스레드 호출에 대한 인수를 보유하는 클래스가있을 수 있습니다. 이러한 경우, internal
의도하지 않은 API 변경으로부터 자신을 보호하는 것 외에 다른 이유가없는 것처럼 표시해야합니다 .
private
키워드는 다른 클래스 또는 구조체 내에서 정의 된 클래스 나 구조체에서 사용할 수 있습니다. 네임 스페이스 내에 정의 된 클래스는 public
또는 만 선언 할 수 있습니다 internal
.
아이디어는 라이브러리를 디자인 할 때 (라이브러리의 클라이언트에 의해) 외부에서 사용하기위한 클래스 만 공개되어야한다는 것입니다. 이렇게하면 클래스를 숨길 수 있습니다.
기타
내부 요소를 사용하는 것보다 사내 솔루션을 개발하는 것이 중요하지 않은 것 같습니다. 일반적으로 클라이언트는 사용자와 지속적으로 연락하거나 코드에 액세스 할 수 있기 때문입니다. 그러나 라이브러리 개발자에게는 매우 중요합니다.
객체 지향 패러다임에 잘 맞지 않는 클래스 또는 메소드가있는 경우 위험한 작업을 수행하고 제어하는 다른 클래스 및 메소드에서 호출해야하며 다른 사람이 사용하지 못하게하려는 경우 .
public class DangerousClass {
public void SafeMethod() { }
internal void UpdateGlobalStateInSomeBizarreWay() { }
}