2010-10-29 35 views
11

Tại sao biên dịch sau đây?Generics and Casting

public IList<T> Deserialize<T>(string xml) 
{    
    if (typeof(T) == typeof(bool)) 
     return (IList<T>)DeserializeBools(xml); 

    return null; 
} 

private static IList<bool> DeserializeBool(string xml) { ... do stuff ... } 

Nhưng điều này không

public MyClass<T> GetFromDb<T>(string id) 
{ 
    if (typeof(T) == typeof(bool)) 
     return (MyClass<T>)GetBoolValue(id); <-- compiler error here 

    return null; 
} 

private static MyClass<bool> GetBoolValue(string id) { ... do stuff ... } 
+5

Lỗi biên dịch là gì? –

+0

Lỗi nói gì? –

+0

Không thể truyền biểu thức loại 'MyClass ' để nhập 'MyClass ' – Magpie

Trả lời

20

Các giao diện lý do công việc là bất kỳ đối tượng thể thực hiện IList<T> (trừ khi nó được biết đến là một thể hiện của một loại niêm phong mà không thực hiện nó, tôi đoán) - vì vậy luôn có một có thể chuyển đổi loại tham chiếu sang giao diện.

Trong trường hợp sau, trình biên dịch là không sẵn sàng để làm điều đó bởi vì nó không thực sự biết rằng T là bool, mặc dù if tuyên bố trước đó, vì vậy nó không biết những gì chuyển đổi thử giữa MyClass<T>MyClass<bool> . Tuy nhiên, các chuyển đổi hợp lệ cho các loại chung loại là khá hạn chế.

Bạn có thể sửa chữa nó khá dễ dàng:

return (MyClass<T>)(object) GetBoolValue(id); 

Nó xấu xí, nhưng nó phải làm việc ... và ít nhất trong trường hợp này nó sẽ không thể gây ra bất kỳ boxing.

+0

Nó có, cảm ơn bạn – Magpie

0

C# 4.0 cho phép khai báo của hiệp phương sai và contravariance trên tham số giao diện và đại biểu các loại.

+0

Điều này không cố gắng sử dụng phương sai chung và phương sai chung chung không áp dụng cho đối số loại giá trị. –

0

gì sẽ xảy ra nếu bạn thay thế

return (MyClass<T>)

với

return (MyClass<bool>) 
+1

Sau đó, nó sẽ không chuyển đổi từ 'MyClass ' thành 'MyClass ' bắt buộc theo kiểu trả về. –