MSIL 방법에서 hidebysig의 목적은 무엇입니까?


92

ildasm 및 C # 프로그램 사용 예

static void Main(string[] args)
{

}

제공합니다 :

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       2 (0x2)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ret
} // end of method Program::Main

hidebysig 구조는 무엇을합니까?

답변:


156

에서 ECMA 335 , 파티션 1의 섹션 8.10.4 :

CTS는 기본 유형에서 표시되는 이름 (숨기기)과 파생 클래스의 레이아웃 슬롯 공유 (재정의) 모두에 대한 독립적 인 제어를 제공합니다. 숨기기는 파생 클래스의 멤버를 이름으로 숨기기 또는 이름 및 서명으로 숨기기로 표시하여 제어됩니다. 숨기기는 항상 멤버의 종류에 따라 수행됩니다. 즉, 파생 필드 이름은 기본 필드 이름을 숨길 수 있지만 메서드 이름, 속성 이름 또는 이벤트 이름은 숨길 수 없습니다. 파생 멤버가 이름으로 숨기기로 표시되면 동일한 이름을 가진 기본 클래스에서 동일한 종류의 멤버가 파생 클래스에 표시되지 않습니다. 멤버가 이름 및 서명으로 숨기기로 표시되면 정확히 동일한 이름 및 유형 (필드의 경우) 또는 메서드 서명 (메서드의 경우)을 가진 동일한 종류의 멤버 만 파생 클래스에서 숨겨집니다. 이 두 가지 형태의 은폐를 구분하는 구현은 전적으로 소스 언어 컴파일러와 리플렉션 라이브러리에 의해 제공됩니다. VES 자체에는 직접적인 영향을주지 않습니다.

(즉시 명확하지는 않지만 hidebysig"이름 및 서명으로 숨기기"를 의미합니다.)

또한 파티션 2의 섹션 15.4.2.2에서 :

hidebysig는 도구 사용을 위해 제공되며 VES에서 무시됩니다. 선언 된 메서드가 메서드 시그니처가 일치하는 기본 클래스 형식의 모든 메서드를 숨기도록 지정합니다. 생략하면 서명에 관계없이 동일한 이름의 모든 메서드를 숨겨야합니다.

예를 들어 다음이 있다고 가정합니다.

public class Base
{
    public void Bar()
    {
    }
}

public class Derived : Base
{
    public void Bar(string x)
    {
    }
}

...

Derived d = new Derived();
d.Bar();

때문에 즉, 유효입니다 Bar(string) 하지 않습니다 숨기기 Bar()때문에 C # 컴파일러의 사용, hidebysig. "hide by name"의미론을 사용했다면 , 여전히 Base로 캐스트하고 그렇게 호출 할 수는 있지만 Bar()type 참조에 대해 전혀 호출 할 수 없습니다 Derived.

편집 : 위의 코드를 DLL로 컴파일하고 ildasming하고 hidebysigfor Bar()및을 제거 Bar(string)하고 다시 ilasming 한 다음 Bar()다른 코드에서 호출하려고 시도했습니다 .

Derived d = new Derived();
d.Bar();

Test.cs(6,9): error CS1501: No overload for method 'Bar' takes '0' arguments

하나:

Base d = new Derived();
d.Bar();

(컴파일 문제가 없습니다.)


4
에서 요약 , 그것은 사이의 차이점 ShadowsOverloadsVB.NET의는.
Mark Hurd

15

THE SKEET의 답변에 따라 그 이유는 Java 및 C #이 클래스의 클라이언트가 기본 클래스의 메서드를 포함하여 동일한 이름을 가진 모든 메서드를 호출 할 수 있도록 허용하기 때문입니다. C ++는 그렇지 않은 반면, 파생 클래스가 기본 클래스의 메서드와 이름이 같은 단일 메서드도 정의하면 동일한 인수를 사용하지 않더라도 클라이언트가 기본 클래스 메서드를 직접 호출 할 수 없습니다. 따라서이 기능은 오버로딩에 대한 두 가지 접근 방식을 모두 지원하기 위해 CIL에 포함되었습니다.

C ++에서는 using지시문 을 사용하여 기본 클래스에서 명명 된 오버로드 집합 하나를 효과적으로 가져올 수 있으므로 해당 메서드 이름에 대한 "오버로드 집합"의 일부가됩니다.


1

Microsoft Docs 에 따르면

파생 클래스의 멤버가 C # new수정 자 또는 Visual Basic Shadows수정 자를 사용하여 선언 되면 기본 클래스에서 동일한 이름의 멤버를 숨길 수 있습니다. C #은 기본 클래스 멤버를 서명으로 숨 깁니다. 즉, 기본 클래스 멤버에 여러 오버로드가있는 경우 숨겨진 유일한 항목은 동일한 서명을 가진 항목입니다. 반대로 Visual Basic은 모든 기본 클래스 오버로드를 숨 깁니다. 따라서 IsHideBySigfalseVisual Basic Shadows 수정 자로 true선언 된 멤버와 C # new수정 자로 선언 된 멤버에 대해 반환합니다 .

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