2013-03-29 35 views
6

Tôi đã tìm kiếm một chút về suy luận kiểu, nhưng dường như tôi không thể áp dụng bất kỳ giải pháp nào cho vấn đề cụ thể của mình.Loại suy luận về các hàm chung lồng nhau

Tôi đang làm rất nhiều công việc với việc xây dựng và truyền tải các chức năng. Điều này dường như với tôi như nó sẽ có thể suy ra các loại int. Điều duy nhất tôi có thể nghĩ là kiểu trả về lambda không được kiểm tra bởi thuật toán suy luận kiểu. Tôi đã loại bỏ logic không cần thiết để hiển thị vấn đề rõ ràng hơn.

Func<T> Test<T>(Func<Func<T>> func) 
{ 
    return func(); 
} 

này biên dịch:

Func<int> x = Test<int>(() => 
    { 
     int i = 0; 
     return() => i; 
    }); 

nhưng điều này cung cấp cho các lỗi "Những lập luận kiểu cho phương pháp không thể được suy ra từ việc sử dụng Cố gắng xác định các đối số loại một cách rõ ràng.":

Func<int> x = Test(() => 
    { 
     int i = 0; 
     return() => i; 
    }); 

Tôi đoán tôi chỉ muốn biết tại sao nó hoạt động theo cách này và bất kỳ cách giải quyết nào.

+0

câu hỏi rất giống nhau, nhưng không hoàn toàn giống nhau http://stackoverflow.com/questions/6090159/inferring-generic-types-with-functional-composition –

Trả lời

7

tôi sẽ nói rằng câu trả lời đúng cho câu hỏi được đưa ra bởi E.Lippert trong SO Why can't an anonymous method be assigned to var?

Nhưng chúng ta hãy chơi với ví dụ của bạn một chút:

Func<Func<int>> f =() => 
{ 
    int i = 0; 
    return() => i; 
}; 

Func<int> x = Test(f); //it compiles OK 

Không có vấn đề trong suy luận kiểu với bạn Func<T> Test<T>(Func<Func<T>> func) tại đây. Vấn đề được ẩn trong đó bạn sử dụng một biểu thức lambda ẩn danh, loại không thể suy ra được. Hãy thử điều này:

var f =() => 
{ 
    int i = 0; 
    return() => i; 
}; 

Nó cung cấp cho Compiler Error CS0815, nói

Không thể gán biểu thức lambda đến một biến cục bộ ngầm, đánh máy

và giải thích là:

Một biểu thức được sử dụng làm trình khởi tạo cho một kiểu được nhập hoàn toàn biến phải có một loại. Bởi vì biểu thức hàm ẩn danh, biểu thức nhóm phương thức và biểu thức chữ rỗng không có một loại, chúng không phải là bộ khởi tạo thích hợp. Một biến được nhập không rõ ràng không thể được khởi tạo với giá trị null trong khai báo của nó, mặc dù sau này nó có thể được gán một giá trị rỗng.

Bây giờ chúng ta hãy thử điều khác:

var x = Test(() => 
{ 
    Func<int> f =() => 0; 
    return f; 
}); 

Nó biên dịch là tốt.Vì vậy, vấn đề với ví dụ ban đầu của bạn đã thực sự với dòng này:

return() => i; 

Chúng ta có thể đi xa hơn và theo những gì Eric Lippert cho biết trong câu trả lời của ông cung cấp một chức năng để quấn này:

static Func<T> GetFunc<T>(Func<T> f) { return f; } 

Bây giờ chúng ta có thể viết lại mã của bạn như:

var x = Test(() => 
{ 
    int i = 0; 
    return GetFunc(() => i); 
}); 

Và nó cũng hoạt động tốt.

Tuy nhiên, theo như tôi hiểu, tất cả điều này là chi phí và bạn chỉ nên cung cấp loại rõ ràng. Trong khi các cách giải quyết này phù hợp, khi bạn cần có một lambda, hãy trả về một đối tượng có kiểu ẩn danh.

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