2010-07-03 37 views
5

Tôi nghĩ rằng tôi phải mất một cái gì đó, tại sao tôi không thể biên dịch này:Tại sao bạn không thể bỏ một kiểu mở chung bị ràng buộc được nhập vào loại bị ràng buộc?

class Foo<T> where T : Bar 
{ 
    T Bar; 
} 

abstract class Bar 
{ } 

class MyBar : Bar 
{ } 

static void Main(string[] args) 
{ 
    var fooMyBar = new Foo<MyBar>(); 
    AddMoreFoos(fooMyBar); 
} 

static void AddMoreFoos<T>(Foo<T> FooToAdd) where T : Bar 
{ 
    var listOfFoos = new List<Foo<Bar>>(); 
    listOfFoos.Add(FooToAdd); //Doesn't compile 
    listOfFoos.Add((Foo<Bar>)FooToAdd); //doesn't compile 
} 

Trả lời

9

Bạn đang làm cho mọi việc một chút khó hiểu hơn là họ cần phải được bằng cách sử dụng một danh sách ở đây ... đó là dễ dàng nhất để xem hiệu quả theo cách này:

// This won't compile 
Foo<Bar> fooBar = new Foo<MyBar>(); 

Cho rằng điều này không biên dịch , sau đó không ngạc nhiên khi bạn không thể thêm số Foo<MyBar> vào số List<Foo<Bar>>

Vậy tại sao không phải là Foo<MyBar> một Foo<Bar>? Bởi vì các lớp chung không phải là biến thể.

Phương sai chung chỉ được giới thiệu trong C# 4 - và nó chỉ hoạt động cho các giao diện và đại biểu. Vì vậy, bạn có thể (trong C# 4) làm:

IEnumerable<MyBar> x = new List<MyBar>(); 
IEnumerable<Bar> y = x; 

nhưng bạn không thể làm được:

IList<MyBar> x = new List<MyBar>(); 
IList<Bar> y = x; 

Tôi có một cuộc nói chuyện cả về biến mà bạn có thể tải về từ NDC 2010 video site - chỉ cần tìm kiếm cho " phương sai ".

3

Nó không biên dịch vì nếu bạn đã gọi phương thức của bạn với một Foo<int> sau đó cuộc gọi sẽ thất bại: bạn đang cố gắng để giả định một loại cụ thể cho thông số chung của bạn.

Những gì bạn cần là sử dụng var listOfFoos = new List<Foo<T>>() thay vào đó, sau đó Add sẽ hoạt động.

(EDIT: như nhau, dàn diễn viên sẽ hoạt động nếu bạn sử dụng Foo<T> - nhưng bạn vẫn không thể giả định trong mã của mình là TBar).

+0

'nếu bạn gọi phương thức của mình bằng Foo thì cuộc gọi sẽ không thành công' => nhưng cuộc gọi này sẽ không biên dịch vì ràng buộc chung, trong đó T: Bar, không? Tuy nhiên, +1 cho Danh sách mới >() vì điều này thực sự giải quyết được vấn đề thực sự của tôi! –

+0

Điểm tốt về ràng buộc. Bối rối là tại sao bạn chấp nhận câu trả lời khác nếu tôi giải quyết vấn đề của bạn tho ... (Jon Skeet hay không! ;-)) –

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