2013-05-27 33 views
5

Đừng nghĩ tiêu đề có thể giải thích những gì tôi đang nói và hơi khó giải thích, vì vậy tôi sẽ để đoạn mã thực hiện cuộc trò chuyện. Bạn có thể sao chép + dán vào LINQPad và chạy nó dưới dạng chương trình C# hoặc thực hiện các điều chỉnh cần thiết như dự án C# thông thường trong studio trực quan (ví dụ: thay đổi cuộc gọi thành Dump() thành Console.Writeline() v.v.) -Đối tượng chung cần có dàn diễn viên mặc dù nó thực hiện giao diện được yêu cầu

Lưu ý rằng nếu bạn bỏ ghi chú dòng trong phương thức doStuff, nó sẽ không biên dịch.

Câu hỏi của tôi là, tại sao tôi cần dàn diễn viên khi generic2 đã triển khai Iab<TA,TB>? Đây có phải là một số điều hiệp phương sai? Tôi vẫn còn trên .NET 3.5.

void Main() 
{ 
    doStuff<a,b>(); 
} 

public void doStuff<TA, TB>() 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    Iab<TA, TB> x = null; 

    x = new generic1<TA, TB>(); 
    x.Go().Dump(); 

    //x = new generic2<TA>(); // <-Cannot implicitly convert type 'UserQuery.generic2<TA>' to 'UserQuery.Iab<TA,TB>'. An explicit conversion exists (are you missing a cast?) 
    x = (Iab<TA, TB>) new generic2<TA>(); 
    x.Go().Dump(); 
} 

public interface Ia 
{} 

public interface Ib 
{} 

public class a : Ia 
{} 

public class b : Ib 
{} 

public interface Iab<TA,TB> 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    string Go(); 
} 

public class generic1<TA, TB> : Iab<TA,TB> 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    public string Go() 
    { 
     return "generic Base called"; 
    } 
} 

public class generic2<TA> : Iab<TA,b> 
where TA : class, Ia, new() 
{ 
public string Go() 
    { 
     return "generic Sub called"; 
    } 
} 

Trả lời

4

Tôi tin rằng điều này là bởi vì bạn sẽ luôn luôn nhận được lỗi rằng khi một hoặc nhiều các loại (trong trường hợp này, TS) không được biết đến tại thời gian biên dịch.

Trình biên dịch không thể đảm bảo rằng doStuff() sẽ được gọi với các loại tương thích, do đó, nó buộc bạn phải truyền.

Để xem lý do tại sao các trình biên dịch không thể thực hiện điều này, hãy thử gọi doStuff() như sau:

public class X: b {} 

... 

doStuff<a, X>(); // Compiles ok but: 

Unhandled Exception: System.InvalidCastException: Không thể bỏ đối tượng của loại 'generic2 1[Demo.Program+X]' to type 'Iab 2 [Demo. Chương trình + X, Demo.Chương trình + Y] '.

Vì vậy, bạn có thể gọi nó bằng các loại sẽ làm hỏng; trình biên dịch sẽ không âm thầm cho phép bạn làm điều đó.

+0

Ah, vâng, tất nhiên. Missed that one :) Cảm ơn! –

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