首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在这种假设的情况下,是否有可能绕过C# <4中的泛型协方差?

在这种假设的情况下,是否有可能绕过C# <4中的泛型协方差?
EN

Stack Overflow用户
提问于 2010-05-08 01:04:31
回答 2查看 144关注 0票数 3

假设我有一个小的Animals继承层次结构:

代码语言:javascript
复制
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的方法。

代码语言:javascript
复制
public interface ITransmogrifier<T> where T : IAnimal {
    T Transmogrify(string s);
}

最后,这里有一个这样做的策略:

代码语言:javascript
复制
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吗?你能从一开始就形成这样的集合吗?

代码语言:javascript
复制
    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");
        }
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-05-08 02:02:18

你不能这样做,因为Transmorgifier<Ape>Transmorgifier<Bat>之间没有类型关系,所以你不能把它们放在同一个泛型列表中(除了List<object>)。显而易见的解决方案就是让ITransmorgifier成为非通用的:

代码语言:javascript
复制
public interface ITransmogrifier
{
    IAnimal Transmogrify(string s);
}

然后你就可以

代码语言:javascript
复制
var list = new List<ITransmogrifier>() {
    new Transmorgifier<Ape>(), new Transmorgifier<Bat>() ...
};
票数 3
EN

Stack Overflow用户

发布于 2010-05-08 04:27:59

李是对的。

正如您的问题所暗示的,您可以在C# 4中通过在T中将ITransmogrifier标记为协变("out")来实现这一点。然后,您可以创建一个List<ITransmogrifier<IAnimal>>并将一个Transmogrifier<Bat>放入该列表中。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2790276

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档