簡體   English   中英

C#強制轉換繼承的通用接口

[英]C# casting an inherited Generic interface

我在轉換我想出的界面時遇到了一些麻煩。 這是C#Windows窗體的MVP設計。 我有一個在表單類上實現的IView類。 還有一個IPresenter,我可以將其歸納為各種特定的Presenter。 每個演示者將根據角色來不同地管理IView,例如,打開對話框以使用AddPresenter輸入新數據集,而不是使用EditPresenter編輯現有數據將數據預加載到表單上。 這些都繼承自IPresenter。 我想這樣使用代碼:

AddPresenter<ConcreteView> pres = new AddPresenter<ConcreteView>();

我基本上可以完成這項工作,但是這些演示者及其管理的視圖都捆綁到了插件中,這些插件在運行時后加載,這意味着我需要一個Manager類,該類作為插件接口采用“ mode”參數。 此模式參數用於工廠方法來創建“添加”或“編輯演示者”,但是由於顯示對話框的調用是稍后進行的,因此我需要通過IPresenter接口進行調用,如下所示:

private IPresenter<IView> pres;
public ShowTheForm()
{
    pres.ShowDialog();
}

現在,在將我的具體實例AddPresenter說給“ pres”成員時,我遇到了問題。 這是我所擁有的簡化版本:

interface IView
{
    void ViewBlah();
}

interface IPresenter<V> where V : IView
{
    void PresBlah();
}

class CView : IView
{
    public void ViewBlah()
    {        
    }
}

class CPresenter<T> : IPresenter<T> where T : IView
{
    public void PresBlah()
    {
    }
}

private void button3_Click(object sender, EventArgs e)
{
    CPresenter<CView> cpres = new CPresenter<CView>();
    IPresenter<IView> ipres = (IPresenter<IView>)cpres;
}

這是錯誤:

Unable to cast object of type 'CPresenter`1[MvpApp1.MainForm+CView]' to type 'IPresenter`1[MvpApp1.MainForm+IView]'.

我可以告訴的Presenter和通用類型規范都是接口的ARE子類,因此我無法理解為什么不進行轉換。

有什么想法嗎?

史蒂夫

問題是通用類型參數。 如果使接口參數協變,則強制轉換將起作用。

這可以通過添加out關鍵字來完成,如下所示:

interface IPresenter<out V> where V : IView
{
    void PresBlah();

}

您可以通過以下MSDN文章了解更多有關其工作原理的信息: 泛協中的協方差和協方差 具有協變類型參數的通用接口部分專門適用於您的問題。

更新:確保您檢查了@phoog和我之間的評論。 如果您的實際代碼接受V作為輸入,則將無法使其協變。 引用的文章和@phoog的答案進一步詳細說明了這種情況。

CPresenter<CView>不是IPresenter<IView> ,就像List<int[]>不是IList<IEnumerable>

想一想。 如果可以獲得對List<int>IList<IEnumerable>引用,則可以向其中添加一個string[] ,這將引發異常。 靜態類型檢查的全部目的是防止此類代碼的編譯。

如果接口允許,則可以將類型參數聲明為協變( IPresenter<out V> where V : ...然后接口的行為就更像IEnumerable<out T> 。這僅在從未使用過類型參數的情況下才有可能在輸入位置。

回到List<int[]>示例,將其視為IEnumerable<IEnumerable> 安全的,因為您無法在IEnumerable<T>引用中添加任何內容。 您只能從中讀取內容,並且將int[]視為IEnumerable是安全的,因此一切都很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM