2015-06-22 18 views
6

tình hình của tôi:tham số kiểu Unconstrained đúc

interface ISomeInterface { 
    void DoSmth<T>(T other); 
} 

class Base : ISomeInterface 
{ 
    public virtual void DoSmth<T>(T other){ 
     // for example do nothing 
    } 
} 

class Derived<T2> : Base { 
    Action<T2> MyAction {get;set;} 

    public override void DoSmth<T>(T other){ 
     if(typeof(T2).IsAssignableFrom(typeof(T))) 
      MyAction((T2) other); 
    } 
} 

này mang lại cho tôi một lỗi: Cannot cast expression of type 'T' to type 'T2' (hoặc Cannot convert type 'T' to 'T2')

Tôi hiểu rằng đó là vì không phải T hoặc T2 thường bị hạn chế với class, nhưng nếu tôi biết - do IsAssignableFrom - rằng tôi có thể sử dụng T khi tôi cần T2, làm thế nào tôi có thể thuyết phục trình biên dịch cho phép nó?

+3

'(T2) (đối tượng) khác' – PetSerAl

+3

' (T2) (đối tượng) khác ' – leppie

+0

Yup, các bạn nói đúng - tôi đã nhận ý tưởng này chỉ vài giây sau khi đăng bài;) Viết câu trả lời và tôi sẽ chấp nhận nó:) – Gerino

Trả lời

3

Trình biên dịch sẽ thấy các số nhận dạng T2 và T và thông báo một cách hữu ích cho bạn rằng các loại đó có vẻ không liên quan. Điều đó hoàn toàn chính xác, vì chúng không có quan hệ: không có ràng buộc chung nào có thể khẳng định bất kỳ mối quan hệ nào giữa chúng (tôi không nói điều đó sẽ có ích ở đây mặc dù :)).

Cho dù đây là một tính năng hay không, có thể tranh chấp. Đôi khi tôi muốn nó chỉ là một cảnh báo, nhưng trong hầu hết các trường hợp, nó rất hữu ích để có nó là một lỗi biên dịch. Số lượng phôi như vậy trong các lớp chung là thấp hơn nhiều so với số lỗi chính tả trong mã 'bình thường' :)

Giải pháp rất đơn giản. Chỉ cần lừa trình biên dịch biết gì về loại nguồn, và nó sẽ bỏ qua kiểm tra kiểu hệ thống phân cấp đối với loại địa điểm:

T theTee = ...; 
object temp = (object)theTee; 
T2 teeTwo = (T2)temp; // ok! 'temp' is now seen as 'object' 

hoặc trong một liner:

T2 teeTwo = (T2)(object)theTee; 

tương tự, bạn có thể sử dụng dynamic (nếu nó có sẵn ở phiên bản Net của bạn):

T theTee = ...; 
dynamic temp = theTee; 
T2 teeTwo = temp; 

và oneliner nên làm việc quá:

T2 teeTwo = (dynamic)theTee; 

mặc dù tôi chưa bao giờ thử điều đó vì tôi cho rằng nó nặng hơn đối tượng truyền qua. Tôi đã không kiểm tra hiệu suất của các đối tượng/phương pháp tiếp cận năng động mặc dù. Chỉ là một linh cảm.

+0

Như tôi đã đọc đầu tiên của tôi mặc dù về năng động được - nó có thể tồi tệ hơn hiệu suất-khôn ngoan. Tôi đoán tôi sẽ đi cho (T2) (đối tượng) - Tôi đã thêm một bình luận giải thích bản thân mình để "thế hệ tương lai". Nếu tôi làm điều đó chỉ sau khi 'IsAssignableFrom == true' thì nó sẽ luôn luôn hoạt động, phải không? – Gerino

+1

Từ những gì tôi nhớ, 'IsAssignableFrom' là kiểm tra Loại-vs-Loại tốt nhất bạn có thể nhận được. Tuy nhiên, đôi khi, tên 'IsAssignableFrom' so với 'IsCastable' có thể làm phiền. Tôi không nhớ bất kỳ trường hợp nào khi 'AssignableFrom' sẽ không gây ra' Castability'. Tôi không thể nói với bạn tôi hoàn toàn chắc chắn. Tôi có thể nghĩ về một số trường hợp góc rất hiếm khi có điều gì đó lạ có thể xảy ra, tuy nhiên, tôi không thấy và cũng không nhớ bất cứ trường hợp nào nó không hoạt động. – quetzalcoatl

+1

@Gerino: Vì vậy, tôi tin chắc rằng 'IsAssignableFrom' ngụ ý" Khả năng cast "theo hướng này. Tuy nhiên, những thuật ngữ này không bằng nhau. Tôi tin rằng 'IsAssignableFrom' có thể giúp bạn nhận được ít nhất một số ** negative negative **. Ví dụ, một '__ComObject' có thể thực sự có thể cast được trong thời gian chạy đến các giao diện, nhưng tôi không nghĩ kiểu của nó sẽ là' IsAssignableFrom' thành các kiểu giao diện đó. Chưa bao giờ kiểm tra. Có thể là thú vị để kiểm tra các bài viết msdn cho trường hợp đó. – quetzalcoatl

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