3 回答

TA貢獻1963條經驗 獲得超6個贊
這是一個非常常見的問題。讓我們重命名您的類型:
abstract class Fruit { } // was BaseViewPresenter
abstract class FruitBowl<T> where T : Fruit // was BaseView
class Apple : Fruit { } // was LoginPresenter
class BowlOfApples : FruitBowl<Apple> { } // was LoginView
您現在的問題是:
我有一個BowlOfApples,繼承自FruitBowl<Apple>。為什么不能將其用作FruitBowl<Fruit>?蘋果是一種水果,所以一碗蘋果是一碗水果。
不,不是。您可以將香蕉放在一碗水果中,但是不能將香蕉放在一碗蘋果中,因此,一碗蘋果不是一碗水果。(并且通過類似的論點,一碗水果也不是一碗蘋果。)由于您可以合法地對這兩種類型執行的操作是不同的,所以它們是不兼容的。
這是StackOverflow傳奇人物Jon Skeet的照片,展示了這個事實:
在此處輸入圖片說明
所需的功能稱為通用矛盾,當編譯器可以證明差異是安全的,并且變化類型是引用類型時,只有接口和委托類型才支持該功能。例如,您可以IEnumerable<Apple>在IEnumerable<Fruit>需要的上下文中使用an ,因為編譯器可以驗證沒有辦法將a Banana放入一系列水果中。
在此站點或網絡上搜索“ C#協方差和逆方差”,您將找到有關此功能如何工作的更多詳細信息。特別是,我有關如何在C#4中設計和實現此功能的系列文章從此處開始:http : //blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in -c-part-one.aspx

TA貢獻1836條經驗 獲得超13個贊
我接受了Eric的回答,因為它很好地解釋了為什么無法實現我想要的東西,但是我還認為我會分享我的解決方案,以防其他人遇到同樣的問題。
我從原始BaseView類中刪除了泛型類型參數,并創建了該類的第二個版本,BaseView其中包含了泛型類型參數及其詳細信息。
我的.Resolve()方法或其他不關心特定類型的代碼使用第一個版本,而任何不關心特定類型的代碼都使用第二個版本,例如BaseView
這是我的代碼最終看起來如何的示例
// base classes
public abstract class BaseViewPresenter { }
public abstract class BaseView : UserControl
{
public BaseViewPresenter Presenter { get; set; }
}
public abstract class BaseView<T> : BaseView
where T : BaseViewPresenter
{
public new T Presenter
{
get { return base.Presenter as T; }
set { base.Presenter = value; }
}
}
// specific classes
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter>
{
// Can now call things like Presenter.LoginPresenterMethod()
}
// updated .Resolve method used for obtaining UI object
public BaseView Resolve(BaseViewPresenter presenter)
{
var type = model.GetType();
var viewType = _dataTemplates[type];
BaseView view = Activator.CreateInstance(viewType) as BaseView;
view.Presenter = presenter;
return view;
}
- 3 回答
- 0 關注
- 645 瀏覽
添加回答
舉報