2016-06-26 6 views
0

最も一般的な例私はcovariantly使用することはできませんcontravariantly-有効なタイプのパラメータが異なる派生型を注入し、基本型のラッパーにそれをキャストし、派生型のいくつかの読み書きのラッパーを構築関与している理由を説明することが分かってきました、 その後、ラップされた値を読み取る;引数型として排他的に使用される型パラメータを持つクラスを共存させることができないのはなぜですか?

class Base { public int base_property; } 
class Derived : Base { public int derived_property; } 
class OtherDerived : Base { public string other_derived_property; } 
interface Wrapper<out T> { 
    void put(T v); 
    T pull(); 
} 
Wrapper<Derived> derived_wrapper = new WrapperImpl<Derived>(); 
Wrapper<Base> cast_wrapper = (Wrapper<Base>)derived_wrapper; 
cast_wrapper.put(new OtherDerived()); 
Derived wrapped = derived_wrapper.pull(); // Surprise! This is an OtherDerived. 

これはなぜ無効かわかります。しかし、Wrapperpullがなく、ラップするプロパティにプライベートゲッターがある場合はどうなりますか? (Wrapper<Base>)derived_wrapperのキャストに関する問題は消えてしまいました。私はそれを置き換えるための問題を見つけることができません。機能は、汎用の最終的な具体的な種類を条件とするため

は具体的には、私はどのような方法を認識していませんよ。

class WrapperImpl<T> : Wrapper<T> where T : Base { 
    public void put(T v) { 
    if(typeof(T).Equals(Derived)) { 
     Console.WriteLine(v.derived_property); // Type `T' does not contain a 
              // definition for `derived_property'... 
    } 
    } 
} 

これは、これらの方法でその機能だけTがに拘束されたタイプの性質を利用することができると信じて私をリード:当然、次のようなタイプをアサートすることは一切使用されません。包まれたプロパティは、元WrapperImplDerived(鋳造される前に)期待OtherDerivedであっても、何の方法がBaseが最も具体的なTがあることが保証されているので、包まれたプロパティがderived_propertyを持っていることを期待することができませんでした。

は、私がここで何かが足りない、または多分これはその場でTを具体化することはできないようにコンパイラの制限であるのですか?

(私はWrapperようなクラスは、いくつかの用途を見つけたが、分散のルールは非常に広範かつ抜本的な現れ、細かいルールが遊びに存在する場合、私は好奇心旺盛だと推測している。)

答えて

0

TWrapperImpl<T>Baseの任意のサブタイプだけでなく、Base自体を制約することができます。 putの機能は、T : BaseT : Derivedに変更するだけで安全にv.derived_propertyにアクセスできるはずです。 OtherDerivedが存在しないderived_propertyにアクセスしようとする中で、(Wrapper<Base>)derived_wrapperキャスト後putに渡されたとき

これはトラブルの元です。

関連する問題