1

以下は fm.AddFoo(new StringFoo()); 行でコンパイルされません。エラーメッセージとともに:

引数 1: 'ClassLibrary2.StringFoo' から 'ClassLibrary2.IFoo' に変換できません

文字列はオブジェクトから継承されるため、これは私には論理的に思えます。

public interface IFoo<T>
{
    void Handle(T value);
}

public class StringFoo : IFoo<string>
{
    public void Handle(string value)
    { }
}

public class ObjectFoo : IFoo<object>
{
    public void Handle(object value)
    { }
}

public class FooManager
{
    private readonly List<IFoo<object>> _foos;

    public FooManager()
    {
        _foos = new List<IFoo<object>>();
    }

    public void AddFoo(IFoo<object> foo)
    {
        _foos.Add(foo);
    }
}

public class Bad
{
    public Bad()
    {
        var fm = new FooManager();

        fm.AddFoo(new StringFoo()); \\ This does not compile
    }
}

ありがとう

4

2 に答える 2

1

IFoo は IFoo のサブクラスのように見えるかもしれませんが、そうではありません。IFoo<> を特定の型に閉じると、IFoo から IFoo のサブクラスが作成されず、共通の階層を持たない別個の異なる型になります。

于 2013-10-31T15:11:23.967 に答える
1

IFoo<>インターフェイスを共変にすることができれば、それは機能します。つまり、その宣言を次のように変更することが許可されている場合です。

public interface IFoo<out T>

( に注意してくださいout)。共分散があると、 anyIFoo<string>も参照型であり、から派生するIFoo<object>ためです。stringobject

ただし:のメンバーでIFoo<>あるHandleメソッドは、反変の方法で型パラメーターを使用します。したがって、インターフェイスを共変 ( ) と宣言することはできませんout。(反変( )と宣言することもできますがin、上記の例では間違った方向に進んでいます。)

ジェネリックにおける共分散と反分散について読んでください。

ここでの根本的な問題は、StringFoo文字列のみを処理することです。したがって、インスタンス (から派生するため、 aは です) を にIFoo<object>渡すことができるため、として使用することはできません。GiraffeGiraffeobjectGiraffeobjectStringFooHandlestring

于 2013-10-31T16:58:33.317 に答える