当两者上的类型参数在 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,并且Container<T>中的T保证实现了IThing,看来我应该能够做到这个转换。

Container<T>不实现IContainer<IThing>吗?

确实如此。

由于Thing实现了IThing,并且Container<T>中的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的东西将无法接受任意Fruit。但是只需要一个Fruit的东西确实可以接受所有Apple

最新更新