假设我有一个小的Animals继承层次结构:
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);
}最后,这里有一个这样做的策略:
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实现的集合中的每个Transmogrifier实例中获取一个IAnimal吗?你能从一开始就形成这样的集合吗?
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");
}
}
}发布于 2010-05-08 02:02:18
你不能这样做,因为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-08 04:27:59
李是对的。
正如您的问题所暗示的,您可以在C# 4中通过在T中将ITransmogrifier标记为协变("out")来实现这一点。然后,您可以创建一个List<ITransmogrifier<IAnimal>>并将一个Transmogrifier<Bat>放入该列表中。
https://stackoverflow.com/questions/2790276
复制相似问题