当两个类型参数在C#中实现公共接口时,如何将泛型强制转换为它实现的接口

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当两个类型参数在C#中实现公共接口时,如何将泛型强制转换为它实现的接口相关的知识,希望对你有一定的参考价值。

请考虑以下代码:

public class Thing : IThing { }

public interface IThing {}

public interface IContainer<out T> where T : IThing { }

// This works
// public class Container<T> : IContainer<T> where T : IThing { }

// This doesn't work
public class Container<T> : IContainer<IThing> where T : IThing {}

internal class Program
{
  private static void Main(string[] args)
  {
    var concreteContainer = new Container<Thing>();
    var abstractContainer = (IContainer<Thing>) concreteContainer;
  }
}

在这一行:

var abstractContainer = (IContainer<Thing>) concreteContainer;

您收到以下运行时错误:InvalidCastException: Unable to cast object of type 'CastTest.Container`1[CastTest.Thing]' to type CastTest.IContainer`1[CastTest.Thing]'.

如果你有Resharper,它会抱怨,Suspecious cast: there is no type in the solution which is inherited from both 'Container<Thing>' and 'IContainer<Thing>'

为什么需要一个继承自两者的类型? Container<T>不实施IContainer<IThing>?由于Thing实施IThing,并且T中的Container<T>保证实施IThing,看起来我应该能够做到这一点。

答案

Container<T>不实施IContainer<IThing>

确实如此。

由于Thing实施IThing,并且T中的Container<T>保证实施IThing,看起来我应该能够做到这一点。

out反过来工作。 out意味着如果类型实现IContainer<Thing>,它也会自动实现IContainer<IThing>。反之亦然。

它被称为out,因为它可以返回一些东西。例如,你可能有

interface IThing<out T> {
    T Prop { get; }
}

现在,IContainer<Apple>会自动实现IContainer<Fruit>,而IContainer<Banana>也会自动实现IContainer<Fruit>。这是有效的,因为返回Apple的东西可以被解释为返回Fruit。但是,如果你只知道它返回Fruit,你不知道Fruit是否是Apple

in以您要求的方式工作。例如,你可能有

interface IThing<in T> {
    void Act(T t);
}

现在,IContainer<Apple>不会自动实现IContainer<Fruit>。这是因为需要Apple的东西将无法接受任意的Fruits。但是只需要Fruit的东西确实接受所有的Apples。

以上是关于当两个类型参数在C#中实现公共接口时,如何将泛型强制转换为它实现的接口的主要内容,如果未能解决你的问题,请参考以下文章

当两个方法同名但参数不同时如何在VB.Net中实现一个接口

如何将泛型类型参数限制为 System.Enum [重复]

Java 泛型

将泛型参数与 impl 中的关联类型匹配

如何要求泛型类型在泛型函数中实现 Add、Sub、Mul 或 Div 之类的操作?

使用多种泛型类型在 Java 中实现抽象泛型方法