2016-03-08 66 views
6

Trình biên dịch nên dịch mã này:Trình biên dịch C# xử lý quá tải các toán tử cast rõ ràng như thế nào?

đến hai phương pháp mà có cùng tên và chữ ký nhưng chỉ khác nhau bởi kiểu trả về của họ, ví dụ

public static Int64 ExplicitCast(MyNumber n) 
... 

public static Double ExplicitCast(MyNumber n) 
... 

Tuy nhiên, chúng tôi không được phép có các phương thức chỉ khác nhau theo kiểu trả về của họ. Điều gì xảy ra sau màn cửa?

+1

_ "Trình biên dịch nên dịch" _ - nói ai? – CodeCaster

+3

Giới hạn trong trình biên dịch C#, không phải trong mã lắp ráp IL. Vì vậy, trình biên dịch C# có thể tạo mã IL sẽ là bất hợp pháp để viết trong C#. – xanatos

Trả lời

7

Về mặt kỹ thuật CLS (Đặc tả ngôn ngữ chung, đặc tả chỉ định một nhánh của máy ảo .NET mà tất cả ngôn ngữ .NET cần hỗ trợ) cho biết tên của phương thức truyền rõ ràng phải là op_Explicit (xem ví dụ http://goo.gl/wn8dHq).

Giới hạn mà bạn không thể có nhiều phương thức có cùng tên và chỉ các loại trả lại khác nhau là giới hạn của C#. Ngôn ngữ IL (đó là ngôn ngữ của máy ảo .NET) không có giới hạn này.

Xem ví dụ: https://stackoverflow.com/a/442100/613130

Một số ngôn ngữ (chẳng hạn như MSIL), tuy nhiên, đừng cho phép quá tải bởi kiểu trả về. Họ cũng phải đối mặt với những khó khăn trên của khóa học, nhưng họ có cách giải quyết, mà bạn sẽ phải tham khảo tài liệu của họ.

https://blogs.msdn.microsoft.com/abhinaba/2005/10/07/c-cil-supports-overloading-by-return-type/

Tuy nhiên, CIL làm phương pháp hỗ trợ quá tải bởi các loại trở lại, mặc dù C#, VB gì không. Để thực hiện điều hành chuyển đổi quá tải C# biên dịch sử dụng tính năng này (tôi biết một cách sử dụng và tôi chắc chắn rằng có nhiều :))

(đó là chính xác các trường hợp yêu cầu ở đây)

Nếu bạn muốn để xem xét các tiêu chuẩn ECMA-335:

I.8.11.1 phương pháp các định nghĩa

chữ ký phương pháp xác định quy ước gọi, gõ các thông số đến phương pháp, và kiểu trả về của phương pháp

Nếu bạn quan tâm để biết làm thế nào phương pháp này có thể được gọi là ... Vâng ... Rõ ràng nếu ngôn ngữ IL hỗ trợ quá tải bởi kiểu trả về, sau đó hướng dẫn call nó phải hỗ trợ nó :-)

Ví dụ http://goo.gl/CS4FPb:

call int64 MyNumber::op_Explicit(class MyNumber) 

vs

call float64 MyNumber::op_Explicit(class MyNumber) 

Lưu ý rằng CLS thường chỉ cấm quá tải dựa trên kiểu trả về ...Nhưng nó có một ngoại lệ cho op_Implicit (các nhà điều hành diễn viên tiềm ẩn) và op_Explicit (toán tử chuyển kiểu tường minh) (so với cùng tập tin ECMA-335):

CLS Rule 38: Properties và phương pháp có thể bị quá tải dựa chỉ trên số và các loại tham số , ngoại trừ các toán tử chuyển đổi có tên op_Implicit và op_Explicit, trong đó cũng có thể bị quá tải dựa trên loại trả về của chúng.

+0

Có thể muốn thêm rằng CLR không thực hiện bất kỳ độ phân giải quá tải 'thực' nào. Nó chỉ đơn giản là sử dụng chữ ký chính xác để tra cứu thành viên - và sau đó gọi các thành viên (ảo nếu cần thiết). Độ phân giải _overload thực tế xảy ra trong trình biên dịch (hoặc trong 'dynamic' nếu bạn thích); các thành viên quá tải là _defined_ trong CIL (với các quy tắc được chỉ định) và chỉ được xác nhận hợp lệ. – atlaste

+0

:-) Đó là chính xác những gì atlast nói :-) – xanatos

1

Tôi không chắc mục đích của câu hỏi của bạn, vì vậy đây là câu trả lời hay nhất tôi có thể cung cấp cho bạn. Đoạn mã trên biên soạn cho một cái gì đó như thế này

MyNumber.op_Explicit: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: callvirt UserQuery+MyNumber.ToInteger 
IL_0007: stloc.0  
IL_0008: br.s  IL_000A 
IL_000A: ldloc.0  
IL_000B: ret   

MyNumber.op_Explicit: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: callvirt UserQuery+MyNumber.ToDouble 
IL_0007: stloc.0  
IL_0008: br.s  IL_000A 
IL_000A: ldloc.0  
IL_000B: ret  

Lý do nó "xuất hiện" không phù hợp là do từ khóa explicit operator. Nó nói với trình biên dịch để tạo mã khác với cách nó thực hiện trong một diễn viên rõ ràng.

Bạn sẽ nhận được một cái gì đó như thế này mà không có nó:

MyNumber.Double2: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: callvirt UserQuery+MyNumber.ToDouble 
IL_0007: stloc.0  
IL_0008: br.s  IL_000A 
IL_000A: ldloc.0  
IL_000B: ret  
Các vấn đề liên quan