Mục đích của hidebysig trong phương pháp MSIL là gì?


92

Sử dụng ildasm và chương trình C #, ví dụ:

static void Main(string[] args)
{

}

cho:

.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

Cấu trúc hidebysig làm gì?

Câu trả lời:


156

Từ ECMA 335 , phần 8.10.4 của phân vùng 1:

CTS cung cấp quyền kiểm soát độc lập đối với cả các tên có thể nhìn thấy từ một loại cơ sở (ẩn) và việc chia sẻ các vị trí bố trí trong lớp dẫn xuất (ghi đè). Ẩn được kiểm soát bằng cách đánh dấu một thành viên trong lớp dẫn xuất là ẩn theo tên hoặc ẩn theo tên và chữ ký. Việc ẩn luôn được thực hiện dựa trên loại thành viên, nghĩa là, tên trường dẫn xuất có thể ẩn tên trường cơ sở, nhưng không ẩn tên phương thức, tên thuộc tính hoặc tên sự kiện. Nếu một thành viên dẫn xuất được đánh dấu là ẩn theo tên, thì các thành viên cùng loại trong lớp cơ sở có cùng tên sẽ không hiển thị trong lớp dẫn xuất; nếu thành viên được đánh dấu là ẩn bằng tên và chữ ký thì chỉ một thành viên cùng loại có tên và kiểu giống hệt nhau (đối với các trường) hoặc chữ ký của phương thức (đối với các phương thức) bị ẩn khỏi lớp dẫn xuất. Việc thực hiện sự phân biệt giữa hai hình thức ẩn này được cung cấp hoàn toàn bởi trình biên dịch ngôn ngữ nguồn và thư viện phản ánh; nó không có tác động trực tiếp đến VES.

(Nó không rõ ràng ngay lập tức từ đó, nhưng hidebysigcó nghĩa là "ẩn bằng tên và chữ ký".)

Cũng trong phần 15.4.2.2 của phân vùng 2:

Hidebysig được cung cấp để sử dụng các công cụ và bị VES bỏ qua. Nó chỉ định rằng phương thức đã khai báo ẩn tất cả các phương thức của các kiểu lớp cơ sở có chữ ký phương thức phù hợp; khi bị bỏ qua, phương thức sẽ ẩn tất cả các phương thức có cùng tên, bất kể chữ ký.

Ví dụ, giả sử bạn có:

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

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

...

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

Điều đó hợp lệ, bởi vì Bar(string) không ẩn Bar(), vì trình biên dịch C # sử dụng hidebysig. Nếu nó sử dụng ngữ nghĩa "hide by name", bạn sẽ không thể gọi nó Bar()trên một tham chiếu kiểu Derived, mặc dù bạn vẫn có thể truyền nó đến Base và gọi nó theo cách đó.

EDIT: Tôi vừa mới thử điều này bằng cách biên dịch mã ở trên để một DLL, ildasming nó, loại bỏ hidebysigcho Bar()Bar(string), ilasming nó một lần nữa, sau đó cố gắng để gọi Bar()từ mã khác:

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

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

Tuy nhiên:

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

(Không có vấn đề biên dịch.)


4
Trong bản tóm tắt , đó là sự khác biệt giữa ShadowsOverloadstrong VB.NET.
Mark Hurd

16

Theo câu trả lời của THE SKEET, ngoài lý do cho điều này là Java và C # cho phép máy khách của một lớp gọi bất kỳ phương thức nào có cùng tên, bao gồm cả những phương thức từ các lớp cơ sở. Trong khi C ++ thì không: nếu lớp dẫn xuất xác định ngay cả một phương thức duy nhất có cùng tên với một phương thức trong lớp cơ sở, thì máy khách không thể gọi trực tiếp phương thức lớp cơ sở, ngay cả khi nó không nhận các đối số giống nhau. Vì vậy, tính năng này đã được đưa vào CIL để hỗ trợ cả hai phương pháp xử lý quá tải.

Trong C ++, bạn có thể nhập một cách hiệu quả một tập hợp quá tải được đặt tên từ lớp cơ sở với một usingchỉ thị, để chúng trở thành một phần của "tập hợp quá tải" cho tên phương thức đó.


1

Theo Microsoft Docs

Khi một thành viên trong lớp dẫn xuất được khai báo với công cụ newsửa đổi C # hoặc công cụ sửa đổi Visual Basic Shadows, nó có thể ẩn một thành viên có cùng tên trong lớp cơ sở. C # ẩn các thành viên lớp cơ sở bằng chữ ký. Nghĩa là, nếu thành viên lớp cơ sở có nhiều quá tải, thì thành viên duy nhất bị ẩn là thành viên có chữ ký giống hệt nhau. Ngược lại, Visual Basic ẩn tất cả các quá tải lớp cơ sở. Do đó, IsHideBySig trả vềfalse trên một thành viên được khai báo với công cụ Shadows sửa đổi Visual Basic và truetrên một thành viên được khai báo với công cụ newsửa đổi C # .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.