2012-01-03 43 views
8

Bên dưới chức năng Compose. Nếu fg là các hàm đơn nhất trả về giá trị, thì Compose(f,g) trả về một hàm khi được gọi trên x thực hiện tương đương với f(g(x)).Thành phần chức năng

static Func<X, Z> Compose<Z, Y, X>(Func<Y, Z> f,Func<X, Y> g) 
{ return x => f(g(x)); } 

Dưới đây là một vài Func giá trị đơn giản mà có thể được bao gồm:

Func<int, bool> is_zero = x => { return x == 0; }; 

Func<int, int> mod_by_2 = x => { return x % 2; }; 

Ví dụ: công trình này:

Console.WriteLine(Compose(is_zero, mod_by_2)(4)); 

Tuy nhiên, nếu tôi thay vì có những phương pháp tĩnh tương đương:

static bool IsZero(int n) { return n == 0; } 

static int ModBy2(int n) { return n % 2; } 

ví dụ tương tự không làm việc với những người. I E. này tạo ra một lỗi thời gian biên dịch:

Console.WriteLine(Compose(IsZero, ModBy2)(4)); 

loại Rõ ràng qua để Compose sửa chữa vấn đề này:

Console.WriteLine(Compose<bool, int, int>(IsZero, ModBy2)(4)); 

Liệu có cách nào để viết Compose như vậy mà nó hoạt động trên các phương pháp tĩnh mà không cần các loại rõ ràng?

Đây có phải là cách tiếp cận tốt để thực hiện Compose không? Có ai có thể cải thiện điều này không?

+0

C# 's cứng trong việc đối xử với các loại chức năng/đại biểu là một điều mà luôn luôn tôi thất vọng khi so sánh với vịt các ngôn ngữ có dạng như JavaScript. –

Trả lời

10

Vấn đề ở đây không phải là sử dụng phương pháp static mà là sử dụng các nhóm phương pháp. Khi bạn sử dụng một tên hàm như là một biểu thức mà không cần gọi nó thì đó là một nhóm phương thức và phải trải qua chuyển đổi nhóm phương thức. Bạn sẽ có cùng một vấn đề với các phương thức ví dụ.

Sự cố bạn đang gặp phải là C# không thể thực hiện suy luận kiểu trả về trên các nhóm phương pháp. Sử dụng Compose(IsZero, ModBy2)) yêu cầu loại trả về được suy ra cho cả IsZeroModBy2 và do đó hoạt động này không thành công.

Đây là giới hạn được biết đến trong khả năng suy luận của trình biên dịch C#. Eric Lippert đã viết một bài trên blog sâu rộng về vấn đề cụ thể này trong đó bao gồm vấn đề này một cách chi tiết

+4

Tôi lưu ý rằng bài viết hơi lỗi thời. Trong trường hợp đặc biệt này, nó là chính xác; bạn không thể suy luận về các nhóm phương pháp vì chúng ta có vấn đề về trứng và trứng; chúng ta không thể xác định các loại delegate là gì cho đến khi chúng ta biết phương thức nào được chọn từ nhóm phương thức và chúng ta không thể thực hiện phân giải quá tải trên một nhóm phương thức cho đến khi chúng ta biết các tham số chính thức của đại biểu *. Ngược lại, các loại * trả về đại biểu * được suy ra nhưng * các kiểu tham số chính thức * đều được biết bằng cách nào đó sau đó suy luận kiểu trả về sẽ hoạt động trên các nhóm phương thức. –

+0

_Khi bạn sử dụng tên hàm làm biểu thức mà không cần gọi nó thì đó là nhóm phương thức và phải trải qua chuyển đổi nhóm phương thức._ OK. Vì vậy, tên 'IsZero' là một nhóm phương pháp. Nhưng trong trường hợp này, rõ ràng chỉ có một phương pháp trong nhóm, và do đó không có sự mơ hồ về kiểu trả về.Rõ ràng là nhóm biên dịch đã quyết định chống lại việc lợi dụng những trường hợp này (các nhóm phương pháp đơn lẻ). Liệu nó có bị cản trở để làm khác không? (Hãy cho tôi biết nếu tôi nên mở một câu hỏi riêng cho điều này ... :-)) – dharmatech

+0

Tất nhiên, một trường hợp rõ ràng khác sẽ là các nhóm phương thức mà tất cả các phương thức trong nhóm có cùng kiểu trả về. – dharmatech

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