この共分散問題なのか。さらにいレンガの壁
-
18-09-2019 - |
質問
書いたASP.NET ページを管理します。彼らは、以下の基底クラスです。
public abstract class FormPageBase<TInterface, TModel> : Page, IKeywordProvider
where TModel:ActiveRecordBase<MasterForm>, TInterface, new()
where TInterface:IMasterForm
{
public TInterface FormData { get; set; }
}
プラスのサブクラスはこちら:
public partial class PersonalDataFormPage : FormPageBase<IPersonalDataForm, PersonalDataForm>, IHasFormData<IPersonalDataForm>, IHasContact
{
}
以下のいusercontrolのページになりたい"消費"の"FormData"のページで読み取り/書き込みます。
そして、より"共有"のユーザーを制御することがしたいの操作は、基本インタフェースのすべての私の形式のサブクラスで...IMasterForm
そのusercontrolを鋳造。FormData(有した鋳ページへ IHasFormData<IMasterForm>
れかのページ IHasFormData<IFormSubclass>
って制約を表すクエリー式をIFormSubclassることは言うまでもIMasterForm
直しとかは出来ないんですかねますのでキャストからのサブクラスの汎用スーパークラスはこの"共分散"、C#4.0こんなことをしたのだろう。
public abstract class FormControlBase<T> : UserControl, IKeywordProvider
where T:IMasterForm
{
protected T FormData { get; set; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
//This cast is failing when my common control's T does not exactly match
// the T of the Page.. even though the common controls TInterface is a base interface to the
//pages TInterface
FormData = ((IHasFormData<T>) Page).FormData;
if (!IsPostBack)
{
PopulateBaseListData();
BindDataToControls();
}
}
protected abstract void PopulateBaseListData();
protected abstract void BindDataToControls();
public abstract void SaveControlsToData();
#region IKeywordProvider
public List<IKeyword> GetKeywords(string categoryName)
{
if(!(Page is IKeywordProvider ))
throw new InvalidOperationException("Page is not IKeywordProvider");
return ((IKeywordProvider) Page).GetKeywords(categoryName);
}
#endregion
}
解決
まず初めに参照することができた言はこのように複雑な問題をより簡潔に表現.お持ちの汎用インタフェース IHasFormData<T>
.いオブジェクトが実施 IHasFormData<IFormSubclass>
.ご希望に変換す IHasFormData<IMasterForm>
.いがあることを参考に変換IFormSubclassにIMasterForm.こ失敗します。
無?
るが、それが正しい計算書の問題は、その問題であるがインタフェースの分散共分散.C#3はタ共分散.C#4、 できることを証明のコンパイラと共分散ることはありません。
についてご説明いいますについて、なぜなのかこのような安心です。例えば、皆さんが授業がありんご、オレンジとフルーツの明らかな場合は、サブクラス。してい IList<Apple>
ると思いますがキャスト IList<Fruit>
.その共変換はできませんのC#4できない法律ではないので安心です。ってしまったのです。しまいます:
IList<Apple> apples = new List<Apple>();
IList<Fruit> fruits = apples;
fruits.Add(new Orange());
// We just put an orange into a list of apples!
// And now the runtime crashes.
この問題は List<T>
公開方法を取るT引数に使います。するためのコンパイラを共変換にインターフェース IHasFormData<T>
, することの証明のコンパイラが IHasFormData<T>
公開ものかかるT引数に使います。だいことを宣言の面 IHasFormData<out T>
, では、ニーモニックの意味"Tのみに表示される出力の位置".コンパイラの次になっていることを確認します請求内容に間違いがないか確認し、開始の共変換。
詳この機能はクライアントまで、フルのC#4は、私のアーカイブのデザインの特徴:
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
他のヒント
C#4.0より前には、正確に型パラメータを一致させるために、一般的なタイプに、すべてのキャストが必要です。 4.0はコとコントラ分散を紹介していますが、実行しようとしているキャストは、以前のバージョンでは不可能です。
私はあなたのこれと非常によく似ベースページは、私は私をどう定義するかである必要があります。
public abstract class ViewBasePage<TPresenter, TView> : Page, IView
where TPresenter : Presenter<TView>
where TView : IView
{
protected TPresenter _presenter;
public TPresenter Presenter
{
set
{
_presenter = value;
_presenter.View = (TView) ((IView) this);
}
}
私はあなたがFormData = ((IHasFormData<T>) (IMasterForm
)Page)).FormData;