2015-07-11 66 views
0

這爲什麼不工作,我如何使它工作?在這種情況下,M直接實現IMessage,我得到一個InvalidCastExceptionC#帶有變量類型參數的Cast類。代碼片段解釋它

public void Subscribe<M>(IMessageListener<M> listener) where M : IMessage 
{ 
    IMessageListener<IMessage> l = (IMessageListener<IMessage>)listener; 
} 

不應該鑄造IMessageListener<M>IMessageListener<IMessage>工作時M實現IMessage

對不起,我不知道如何描述它。

//編輯 的IMessageListener類看起來是這樣的:

public interface IMessageListener<M> where M : IMessage 
{ 
    void ProcessMessage(M message); 
} 
+0

糟糕!對於那個誤導性的答案,我很抱歉 - 我剛剛根據我以前讀過的內容發佈了它。希望這個答案可以幫助你 - http://stackoverflow.com/questions/19166133 – potatopeelings

+0

爲什麼你需要施放它?將它用作'IMessageListener ' - 稍後調用'listener.ProcessMessage(message)'。 –

回答

0

簡短的回答:不,應該不行。

public class MessageA : IMessage 
{ 
    public int SpecificAField; 
} 

public class MessageB : IMessage {} 

public class MessageAListener : IMessageListener<MessageA> 
{ 
    public void ProcessMessage(MessageA message) 
    { 
     messageA.SpecificAField = 3; 
    } 
} 

如果編譯器要讓Subscribe<MessageA>?投MessageAListenerIMessageListener<IMessage>,那麼你可以通過它MessageB

然後MessageAListener將嘗試設置SpecificAFieldMessageB,它不會有一個。


這不起作用,因爲IMessageListener<T>逆變T - 它僅僅引用T作爲輸入。因此,您可以將IMessageListener<IMessage>投射到IMessageListener<MessageA>,因爲它會愉快地接受MessageA作爲輸入代替IMessage

要執行需要IMessageListener<T>演員是T - 它必須完全引用T作爲輸出。然後,您可以將IMessageListener<MessageA>轉換爲IMessageListener<IMessage>,因爲可以將真實返回類型MessageA轉換爲期望返回類型IMessage

+0

好吧,我明白了。我的問題是,我有一個類型爲鍵的字典和類型實例的列表作爲值,實現IMessage。那麼我將如何實現呢? – Zoidy

+0

你知道我在哪裏可以閱讀更多關於協變性的內容嗎?它對我來說是全新的 – Zoidy

+0

@Zoidy混合泛型和類型對象通常是一個錯誤。泛型在編譯時處理不同的類型;類型對象在運行時處理不同的類型。 Eric Lippert在協作開始時有一個很好的系列[here](http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx )。 – Rawling