2009-03-17 28 views

Trả lời

145

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

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

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

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

hidebysig là cung cấp cho việc sử dụng các công cụ và bị VES bỏ qua. Nó chỉ định rằng phương thức được khai báo ẩn tất cả các phương thức của lớp cơ sở các loại có phương thức khớp chữ ký; khi 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ý.

Như một 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(); 

Đó là hợp lệ, vì Bar(string)không ẩn Bar(), bởi vì biên dịch C# sử dụng hidebysig. Nếu nó sử dụng ngữ nghĩa "ẩn theo tên", bạn sẽ không thể gọi số Bar() ở tất cả trên tham chiếu loại Derived, mặc dù bạn vẫn có thể truyền nó đến Base và gọi 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ỏ hidebysig cho 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.)

+2

Trong [tóm tắt] (http://stackoverflow.com/a/4760614/256431 "Shadows vs Overloads in VB.NET"), đó là sự khác biệt giữa 'Shadows' và' Overloads' trong VB.NET. –

14

Như mỗi câu trả lời THE bắn đĩa bay Skeet, Ngoài ra 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ả các phương thức từ các lớp cơ sở. Trong khi C++ không: nếu lớp dẫn xuất định nghĩa ngay cả một phương thức duy nhất có cùng tên như một phương thức trong lớp cơ sở, thì máy khách không thể trực tiếp gọi phương thức lớp cơ sở, ngay cả khi nó không lấy cùng các đối số. Vì vậy, tính năng được đưa vào CIL để hỗ trợ cả hai cách tiếp cận quá tải.

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

Các vấn đề liên quan