2014-12-23 16 views
5

biên dịch C# có thể suy ra một cách chính xác loại s (string) trong những đoạn:IEnumerable <Func<T,S>> và LINQ suy luận kiểu

Func<int, string, string> f1 = (n, s) => s.Substring(n); 
Func<int, Func<string, string>> f2 = n => s => s.Substring(n); 

Nhưng nó không thể trong vụ việc này [1]:

var numbers = Enumerable.Range(1, 10); 
IEnumerable<Func<string, string>> fs = numbers.Select(n => s => s.Substring(n)); 

để làm cho nó làm việc người ta phải làm một cái gì đó như thế này:

var fs = numbers.Select(n => new Func<string, string>(s => s.Substring(n)); 

hoặc

var fs = numbers.Select(f2); 

Và câu hỏi đặt ra là - tại sao suy luận kiểu không hoạt động trong [1] nếu tất cả thông tin cần thiết về các loại được biết trước?

Trả lời

7

Tất cả thông tin về loại không phải là đã biết trước đó. Trong đoạn mã hoạt động đầu tiên của bạn, bạn đang nói trên cả hai dòng ủy quyền loại bạn muốn s => s.Substring(n) được chuyển đổi thành.

Trong đoạn thứ hai của bạn, nơi duy nhất có thông tin đó là gán kết quả của Select ... và không được sử dụng như là một phần của quá tải và suy luận kiểu khi trình biên dịch đang hoạt động những gì các cuộc gọi Select chính nó có nghĩa là.

Vì vậy, các tùy chọn là:

  • làm điều đó trong hai bước, sử dụng f2
  • Cast biểu thức lambda trong Select cuộc gọi, hoặc sử dụng một nhà điều hành new theo đoạn mã của bạn
  • Cung cấp nhập đối số cho Select trực tiếp:

    var fs = numbers.Select<int, Func<string, string>>(n => s => s.Substring(n)); 
    
+0

Cảm ơn câu trả lời nhanh chóng của bạn. Đó là một sự xấu hổ rằng nó không hoạt động theo cách tôi nghĩ trong C#. Có thể tôi bị hư hỏng bởi f #, nơi những thứ như cho fs: (string -> string) seq = numbers |> Seq.map (vui vẻ n -> fun s -> s.Substring (n)) là có thể. – rkrahl

+0

@rkrahl: Vâng, suy luận kiểu trong F # chắc chắn là mạnh mẽ hơn. –

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