2012-09-27 37 views
7

Tôi có một tình huống mà tôi có một lớp chấp nhận một thể hiện của một kiểu đối tượng nhất định trong tham số kiểu chung của nó. Việc bố trí là một cái gì đó như thế này:Trả về chung mà không biết loại

public abstract BaseClass { ... } 
public DiamondClass : BaseClass { ... } 
public SilverClass : BaseClass { ... } 

public Handler<T> where T : BaseClass { ... } 

Tôi muốn để có thể tạo ra một phương pháp để trả về một thể hiện của Handler<DiamondClass> hoặc Handler<BaseClass> mà không cần xác định loại khi đầu vào. Tôi đã thử một cái gì đó dọc theo những dòng:

public Handler<BaseClass> GetHandler(HandlerType type) 
{ 
    switch(type) 
    { 
     case HandlerType.Diamond: return new Handler<DiamondClass>(); 
     case HandlerType.Silver: return new Handler<SilverClass>(); 
     default: throw new InvalidOperationException("..."); 
    } 
} 

Nhưng điều này sẽ không làm việc, bởi vì rõ ràng Handler<DiamondClass> sẽ không đúc ngầm để Handler<BaseClass>. Tôi có thể xác định nó như thế này:

public Handler<T> GetHandler<T>(HandlerType type) where T : BaseClass 
{ 
    switch(type) 
    { 
     case HandlerType.Diamond: return (Handler<T>)new Handler<DiamondClass>(); 
     case HandlerType.Silver: return (Handler<T>)new Handler<SilverClass>(); 
     default: throw new InvalidOperationException("..."); 
    } 
} 

Nhưng bây giờ tôi cần phải gọi GetHandler<DiamondClass> hoặc GetHandler<BaseClass>. Và điều đó đánh bại mục đích của việc có một phương thức trả về trình xử lý thích hợp dựa trên một enum, mà không biết loại đó. Tôi hy vọng rằng tôi có thể xác định một đối tượng Type và vượt qua nó, như vậy:

Nhưng dường như C# sẽ không cho phép loại ngu xuẩn đó. Tôi đã đi về điều này một số cách khác nhau, và tôi muốn nghĩ rằng có một cách để làm điều đó, nhưng tôi stumped.


(Tôi thực sự đã làm việc này bằng cách trả lại một đối tượng dynamic, nhưng tôi muốn tránh nó nếu có thể, vì nó mất bất kỳ an toàn loại và hỗ trợ Intellisense.)

+0

Có gì sai với 'var handler = Handler ();', tôi không thấy vấn đề bạn đang cố giải quyết. – CaffGeek

+3

nếu bạn phải kiểm tra loại bên trong của một phương pháp chung chung, tôi luôn luôn đặt câu hỏi về tính hữu dụng của phương pháp đó. –

+0

@RobA Hãy nhớ rằng tôi đã đơn giản hóa ví dụ rất nhiều vì mục đích giải thích. Một phần của vấn đề là tôi muốn nó thuộc về một điều khiển người dùng, và tôi không thể định nghĩa nó là chung chung vì nó giết chết nhà thiết kế. – KChaloux

Trả lời

9

Đây là nơi đồng phương sai đi vào hoạt động, hiệp phương sai và đối nghịch chỉ hoạt động trên giao diện và đại biểu, do đó, để giải quyết vấn đề của bạn, chỉ cần xác định giao diện mới IHandler làm đồng biến thể với out. là đồng biến thể:

public interface IHandler<out T> where T : BaseClass 
{ 
} 

Một giao diện có một tham số kiểu hiệp biến cho phép các phương pháp của mình để trở lại các loại có nguồn gốc hơn so với những quy định bởi tham số kiểu

Nó sẽ làm việc. Thông tin thêm là here

+2

+1 linkyyyy – JonH

+0

Xin chào, tôi không biết chúng tôi có thể làm điều đó, với loại ! Đậu mát. Tôi thích học những thứ này. Chỉnh sửa: Chỉ cần dùng thử. Bạn là một phao cứu sinh. Nó đơn giản hóa cách khái niệm nhiều hơn những gì tôi nghĩ tôi phải làm. Tôi đã WONDERING lý do tại sao nó sẽ không chấp nhận đứa trẻ như một loại cơ sở. – KChaloux

+0

@KChaloux: vì công cụ này chỉ hoạt động với INTERFACE và DELEGATE nếu tôi hiểu chính xác? nó có nghĩa là gì * đứa trẻ như một loại cơ sở *? –

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