3

動物の小さな継承階層があるとします。

public interface IAnimal {
    string Speak();
}

public class Animal : IAnimal {
    public Animal() {}
    public string Speak() {
        return "[Animal] Growl!";
    }
}

public class Ape : IAnimal {
    public string Speak() {
        return "[Ape] Rawrrrrrrr!";
    }
}

public class Bat : IAnimal {
    public string Speak() {
        return "[Bat] Screeeeeee!";
    }
}

次に、にstrings変換する方法を提供するインターフェースを次に示しますIAnimals

public interface ITransmogrifier<T> where T : IAnimal {
    T Transmogrify(string s);
}

そして最後に、これを行うための1つの戦略があります。

public class Transmogrifier<T> : ITransmogrifier<T> where T : IAnimal, new() {
    public T Transmogrify(string s) {
        T t = default(T);
        if (typeof(T).Name == s)
            t = new T();
        return t;
    }
}

さて、質問です。このプログラムが正しくコンパイルおよび実行されるように、[1]、[2]、および[3]とマークされたセクションを置き換えることは可能ですか?[1]、[2]、[3]以外の部分に触れずにそれを行うことができない場合でも、IAnimalの任意の実装を含むコレクション内のIAnimalの各インスタンスから取得できますか?Transmogrifierそもそもそのようなコレクションを作ることさえできますか?

    static void Main(string[] args) {
        var t = new Transmogrifier<Ape>();
        Ape a = t.Transmogrify("Ape");
        Console.WriteLine(a.Speak());  // Works!

        // But can we make an arbitrary collection of such animals?
        var list = new List<Transmogrifier< [1] >>() {
            // [2]
        };

        // And how about we call Transmogrify() on each one?
        foreach (/* [3] */ transmogrifier in list) {
            IAnimal ia = transmogrifier.Transmogrify("Bat");
        }
    }
}
4

2 に答える 2

4

リーは正しい。

質問で示唆しているように、C#4では、TでITransmogrifierを共変( "out")としてマークすることで、これを行うことができます。次に、を作成してそのリストList<ITransmogrifier<IAnimal>>に入れることができます。Transmogrifier<Bat>

于 2010-05-07T20:27:58.787 に答える
3

Transmorgifier<Ape>との間に型の関係がないTransmorgifier<Bat>ため、これを行うことはできません。したがって、それらを同じ汎用リストに入れることはできません(を除くList<object>)。明らかな解決策は、ITransmorgifier非ジェネリックにすることです。

public interface ITransmogrifier
{
    IAnimal Transmogrify(string s);
}

その後、あなたは持つことができます

var list = new List<ITransmogrifier>() {
    new Transmorgifier<Ape>(), new Transmorgifier<Bat>() ...
};
于 2010-05-07T18:02:17.980 に答える