[英]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.