2017-06-07 4 views
0

私は、Contravarianceを使用するときに、以下に何か作用して苦労しています。私の理解は、共分散は基本型から派生型を返すことができるところです。 Contravarianceは、基本型の派生型を引数としてクラスに渡すことができる場所です。c#.net 4.0共変量対変量

だから私は、以下のインターフェース(反変)持っている:ジェネリック型を考慮し

public interface IBase<in T> where T: BaseModel 
{ 
     void Process(T model); 
} 

私は、抽象クラスを持っている

public abstract class Base<T>: IBase<T> where T: BaseModel 
{ 
    public virtual void Process(T model) 
    { 
     // throw new System.NotImplementedException(); 
    } 
} 

と別の具体的なクラス

public class Parent: Base<ParentModel> 
{ 
    public override void Process(ParentModel model) 
    { 
     // throw new System.NotImplementedException(); 
    } 
} 

をされます入力としてのみ使用され、戻り値の型ではありませんが、なぜ私は以下を行うことができません:

IBase<BaseModel> baseContravariant = new Parent(); 
// This doesn't compile. I will eventually have a list of IBase<BaseMode> to which I'd like to pass in different parent instances. 

私は以下の共分散を使用したもう1つの例があります。

public interface IBase<out T> where T : BaseModel, new() 
{ 
    T ProcessAndGet(); 
} 

抽象

public abstract class Base<T>: IBase<T> where T: BaseModel, new() 
{ 
    public virtual T ProcessAndGet() 
    { 
     var result = new T() as BaseModel; 

     // More shizzle here 
     return (T)result; 
    } 
} 

コンクリートIがあり、上記の例に多くのコードですが、私はを容易にするためにそれを削除した

IBase<BaseModel> baseInstance = new Base<BaseModel>(); 
IBase<BaseModel> derived = new Parent(); 
baseInstance = derived; 

行うことができます今

public class Parent : Base<ParentModel> 
{ 
    public override ParentModel ProcessAndGet() 
    { 
     var x = base.ProcessAndGet(); 
     return x; 
    } 
} 

読んで(うまくいけば!):-)

答えて

0

この場合、コントラバリアントは、指定された型の型または "より特殊化された型"(=>基本型から派生する型)を渡す必要があることを意味します。

最初の例のParent実装ではParentModelしか処理できないため、BaseModelインスタンスを渡すことはできません。 new Parent().Process(new BaseModel())を実行しようとするとコンパイルされません。したがって、それをIBase<BaseModel>にキャストすることは無効です。 (ParentModelBaseModelのサブクラスであると仮定します)。

この場合、逆分散モデルは、IBase<in T>が「Tを消費する」と考えることによって、より簡単に推論することができます。したがって、IBase<ParentModel>は "ParentModelを消費します"。これは、ParentModelのインスタンスであるか、または1つとして扱うことができる(実際にはサブクラスのみ)値を渡すことができることを意味します。

2番目の例では、 "共変"である<out T>を使用しています。これは「それはTのインスタンスを生成する」と表現することができます。したがって、ParentModelを「生成する」クラスは自動的にBaseModelの「プロデューサ」です。ParentModelBaseModelに、IBase<ParentModel>にはIBase<BaseModel>にもキャストできます。

+0

応答と有益な回答ありがとう。私が提供した2番目の例は、ステップの点で同様のことを行います。 ParentクラスはParentModelのみを取りますが、これを基本クラスに割り当てることはできますか?私はそれがイン/アウト機能の背後にある意図だと思った... – tones

+0

私は共変型についてのパラグラフを追加しました。私はあなたの実際の質問が正直であることは確かではありません。(簡単な言葉でそれを説明する以外には、「プロデューサー」と「消費者」のすべてを置き換えることが常に助けになりました) –

+0

Aah that makes sense 。 2番目の点については質問はありませんでした。あなたが理解しているものと働いているものとを比較し、他のものはそうしなかったということを、あなたがもっと言うようなものでした。要するに、共分散のために、あまり具体的でないタイプに割り当てることができますが、反差異を割り当てることはできません。うまくいけば私はそれを正しく理解した。 – tones