2016-11-28 70 views
10

Tôi có hàm tổng quát này trong F # có sử dụng (-) điều hành:Điều Hành (-) được sử dụng trong F # tăng phương pháp chỉ định không được hỗ trợ ngoại lệ từ C#

let inline sub a b = a - b

Bây giờ tôi gọi chức năng này từ C#:

int a = sub<int, int, int>(4, 1);

Điều này đặt ra một lỗi:

Unhandled Exception: System.NotSupportedException: Specified method is not supported. at ProjA.MainClass.Main (System.String[] args) [0x00000] in <4f209fa43741462db3b8f73ac83c35a2>:0 [ERROR] FATAL UNHANDLED EXCEPTION: System.NotSupportedException: Specified method is not supported. at ProjA.MainClass.Main (System.String[] args) [0x00000] in <4f209fa43741462db3b8f73ac83c35a2>:0

Xin lưu ý rằng điều này làm việc tốt cho (+) nhà điều hành hoặc không có từ khóa nội tuyến.

1) Tôi có đang làm điều gì sai hoặc đây có phải là lỗi không?

2) Có cách nào để khắc phục vấn đề này không (nhưng tôi cần từ khóa nội tuyến để thực hiện chức năng này chung)?

3) Bạn đã trải nghiệm điều gì đó tương tự khi gọi hàm f # từ C#, bạn đã giải quyết nó như thế nào?

Tôi đang sử dụng Mono 4.8 trên macOS Sierra.

+0

@EJoshuaS Trình biên dịch tự thực thi ba tham số, một tham số cuối cùng cho kiểu trả về. Loại đối số không thể được suy ra tự động bởi trình biên dịch. Như tôi đã đề cập, điều kỳ lạ là khi tôi thay đổi (-) thành (+) mọi thứ hoạt động tốt mà không có ngoại lệ. – mateuszlewko

+0

Có, xin vui lòng bỏ qua bình luận trước đây của tôi, tôi thấy rằng một khi tôi đã thử nó bản thân mình. Tôi hơi ngạc nhiên bởi loại hành vi đó (tôi đã thấy chính xác điều tương tự trên máy của tôi). Dường như từ khóa "inline" [có thể hơi lạ] (http://stackoverflow.com/questions/4413324/how-does-f-inline-work) khi gọi từ C# đến F # - trên thực tế, khi tôi xóa chức năng nội tuyến nó hoạt động chính xác - nhưng tôi hơi bối rối về lý do tại sao điều này sẽ làm việc cho "+" nhưng không phải "-". Tôi thực sự thực sự muốn thấy một lời giải thích cho lý do tại sao điều này là quá nếu ai đó biết. – EJoshuaS

+1

Tôi sẽ ngạc nhiên rằng điều này thậm chí hoạt động - Tôi nghi ngờ rằng bạn có lẽ là shadowing định nghĩa của cái gì khác nếu bạn sử dụng +. Đối với nội tuyến, trình biên dịch F # không thực sự tạo ra một hàm, nó chỉ tạo ra một số siêu dữ liệu mà nó có thể sử dụng.Thực tế là trình biên dịch C# thấy nó ở tất cả là do đó đáng ngạc nhiên –

Trả lời

7

Nói chung, các hàm được khai báo là inline sẽ không thể sử dụng được (hoặc sẽ không hoạt động giống như từ F #) từ các ngôn ngữ khác. Chúng được thay thế tại trang gọi là một tính năng của trình biên dịch F #, không được hỗ trợ bởi C# và các ngôn ngữ CLR khác. Đây là một lợi thế đáng kể của F # trên các ngôn ngữ khác.

Tuy nhiên, có một số ngoại lệ. Có thể viết các hàm F # inline thực hiện công văn dựa trên kiểu thời gian chạy, sau đó có thể sử dụng được từ C# và các ngôn ngữ khác. Thông thường, chúng sẽ không nhận được cùng một IL khi được sử dụng từ C# khi chúng thực hiện từ F # đối với một số kiểu nhất định (các trình xử lý cụ thể cho các kiểu nguyên thủy sẽ không được xử lý). Đây là lý do tại sao (+) hoạt động - bạn có thể thấy this in the code for the operator, trong đó (+) gọi AdditionDynamic<(^T),(^U),(^V)> x y. Lưu ý rằng (-)is missing the runtime dispatched version và được đánh dấu rõ ràng là [<NoDynamicInvocation>], đó là lý do tại sao nó không hoạt động từ C#.

Điều này có hiệu quả cùng một giới hạn trong C# đã khiến mọi người yêu cầu những thứ như IArithmetic (* sử dụng Lưu trữ Internet vì nó bị ẩn trong Kết nối) trong nhiều năm. F # hoạt động xung quanh điều này thông qua statically resolved type parameters, nhưng đây là tính năng dành riêng cho F # và sẽ không hoạt động với C# và các ngôn ngữ khác. Việc gói hàm thông qua F # không kích hoạt nó trong C#.

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