c# - 无法在列表 C# 中保存通用接口(interface)实现

标签 c# generics covariance contravariance invariance

如何使列表包含通用接口(interface)的所有不同实现?

例如

public class Animal { // some Animal implementations }
public class Dog : Animal { // some Dog implementations }
public class Snake : Animal { // some Snake implementations }

public interface ICatcher<T> where T: Animal
{
    // different animals can be caught different ways.
    string Catch(T animal);
}

public class DogCatcher : ICatcher<Dog> 
{ 
    string Catch(Dog animal) { // implementation }
}

public class SnakeCatcher : ICatcher<Snake> 
{ 
    string Catch(Snake animal) { // implementation }
}

我想将所有捕手放在一个列表中,例如,

public class AnimalCatcher
{
     // this will hold the catching method an animal catcher knows (just something similar)
     public IEnumerable<ICatcher<Animal>> AnimalCatcher = new List<ICatcher<Animal>>
     {
          new DogCatcher(),
          new SnakeCatcher()
     }
}

我知道它是处理 C# 中的通用修饰符(协方差、逆变和不变)的东西,但无法让它工作。

尝试:在

中添加“out”
public interface ICatcher<out T> where T: Animal
{
    // different animals can be caught different ways.
    string Catch(T animal);
}

但给出了编译时错误:

"The type parameter 'T' must be contravariantly valid on 'ICatcher.Catch(T)'. 'T' is covariant."

我做错了什么?

最佳答案

您需要对动物进行某种类型统一,并且需要删除 ICatcher 的通用声明并使其成为具体类型:

public interface IAnimal {}

public class Dog : IAnimal {}
public class Snake : IAnimal {}

public interface ICatcher
{
    // different animals can be caught different ways.
    string Catch(IAnimal animal);
}

然后你就可以拥有像这样的捕手集合:

public class AnimalCatcher
{
     // this will hold the catching method an animal catcher knows (just something similar)
     public IEnumerable<ICatcher> AnimalCatcher = new List<ICatcher>
     {
          new DogCatcher(),
          new SnakeCatcher()
     }
}

预计到达时间:这是 repl.it演示如何使用接口(interface)进行设置。尽管在各自的 Catch 实现中,您必须强制转换 IAnimal 接口(interface)(如果您需要访问特定于特定动物实现的实例变量)

关于c# - 无法在列表 C# 中保存通用接口(interface)实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58803406/

相关文章:

c# - DownloadFileAsync 与 DownloadFileTaskAsync

c# - 当我们在 C# 中访问字符串的 ' Length ' 属性时会发生什么?

c# - 确保 C# 中的多播委托(delegate)执行列表顺序?

c# - 推断或忽略嵌套 C# 接口(interface)中的嵌套泛型

c# - 函数的协变分配需要显式参数

c# - 将 IFoo<T> 转换为 IFoo<object> 的一般方法

c# - WCF - 无法解析 [WebGet] 符号 - 我做错了什么?

java - 使用泛型获取 java.lang.Class

java - 如何获取泛型类型 T 的类实例?

php - 特化中的参数类型协方差