2012-11-13 30 views
5

Tôi nhận được một lỗi lạ với Visual Studio 10 (và bây giờ 11 là tốt). Tôi có một phương pháp khuyến nôngKhông thể tìm thấy định nghĩa mặc dù intellisense liệt kê nó?

public static S Foo<S, T>(this S s) where S : IEnumerable<T> 
{ 
    return s; 
} 

Bây giờ nếu tôi gọi

"".Foo(); // => 'string' does not contain a definition for 'Foo' and no extension method 'Foo' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) 

Tôi không ở tất cả hiểu biết những gì đang xảy ra dưới mui xe. Phần gây phiền nhiễu là danh sách số intellisense Foo cho IEnumberable<T> s. Tốt nhất nó nên có một type can't be inferred error.

Nếu tôi gọi nó theo cách này:

Extension.Foo(""); // => The type arguments for method 'Extension.Foo<S,T>(S)' cannot be inferred from the usage. Try specifying the type arguments explicitly. 

Tại sao không thể gõ được suy ra trong trường hợp trên?

thêm:

Giả sử tôi có:

public static S Foo<S, T>(this S s, T t) where S : IEnumerable<T> 
{ 
    return s; 
} 

Và nếu tôi gọi:

"".Foo(1); 

Các loại suy luận là rất thông minh ở đây để nói với tôi rằng Foo nên trả lại IEnumerable<int>string là n ot tất cả những gì !!

Vì vậy, nếu trình biên dịch có thể biết Foo đang mong đợi một char làm đối số đầu tiên, thì tại sao ví dụ đầu tiên của tôi chỉ biên dịch? Nói cách khác, tại sao trong ví dụ đầu tiên trình biên dịch biết T trong trường hợp đó là char?

Như dự kiến ​​công trình này cho ví dụ thứ hai:

"".Foo('l'); 

Tôi chỉ tự hỏi tại sao không thể T được suy ra như char trong ví dụ đầu tiên, sau khi tất cả chuỗi là IEnumberable<char>.


Edit:

tôi có câu trả lời từ SLaks. Nhưng thật kỳ lạ khi C# không làm điều này (kiểu suy luận kiểu) xem xét trình biên dịch có tính đến các ràng buộc chung cũng như khi phơi bày các phương thức sẵn có để hoạt động trên một đối tượng.

Nói cách khác:

public static S Foo<S, T>(this S s) 
{ 
    return s; 
} 

làm Foo sẵn trên tất cả object s.

public static S Foo<S, T>(this S s) where S : IEnumerable<T> 
{ 
    return s; 
} 

làm Foo sẵn trên tất cả IEnumerable<T> s kể từ nó biếtSIEnumerable<T>.Vì vậy, tôi đã nghĩ rằng C# sẽ thậm chí suy ra loại T! Cảm ơn mọi người! ;)

Trả lời

9

Công cụ suy luận loại không đủ thông minh để thực hiện điều đó.

Suy luận kiểu C# chỉ xem xét phương thức chữ ký.
Generic constraints are not part of the signature.

T không được sử dụng trực tiếp trong chữ ký, trình biên dịch sẽ không phỏng đoán nó.

+4

Cài đặt cụ thể các loại chung sẽ hoạt động: '" ".Foo ();' –

+0

@ RenéWolferink hiển nhiên, câu hỏi của tôi là về lý do không tự động suy ra loại. – nawfal

+0

Đó là lý do tại sao tôi đã thêm nó làm nhận xét chứ không phải là câu trả lời, chỉ để hoàn thành. ;) –

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