【问题标题】:Why cast of the interface with generic parameter to the same interface with less constraints does not work?为什么将具有通用参数的接口转换为具有较少约束的同一接口不起作用?
【发布时间】:2025-12-31 04:45:11
【问题描述】:

我有这种情况:

private IHandle<ICommand> Map<T>(IHandle<T> handle)
    where T : ICommand
{
    return (IHandle<ICommand>) handle;
}

该代码给出运行时错误。 但似乎IHandle&lt;ICommand&gt;IHandle&lt;T&gt; 更通用(因为where T : ICommand 约束)。我不明白为什么类型系统不能允许这种转换。我该怎么办?

【问题讨论】:

  • 具体错误是什么?
  • @Clay07g 无法将 IncrementHandler' 类型的对象转换为类型 'IHandle`1[ICommand]'。
  • InvalidCastException
  • 只有在 IHandle&lt;T&gt;T 是协变的情况下才会起作用,这意味着它只返回 T 并且永远不会将其作为参数或用于设置属性,并且定义必须是IHandle&lt;out T&gt;docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…

标签: c# generics types casting


【解决方案1】:

假设它是IList&lt;T&gt; 而不是IHandle&lt;T&gt;。以下方法不起作用:

    IList<Bar> bars = new List<Bar>();
    IList<Foo> foos = (IList<Foo>)bars;

    public class Foo { }
    public class Bar : Foo { }

因为如果您尝试拨打foos.Add(new Foo()); 会发生什么?底层类型是Bar 的列表,它不能接受任何旧的Foo 添加到它,否则它将不再是Bars 的列表。其他人可能仍然有对它的引用,并且需要以Bar 类型遍历它的所有元素。所以接口需要是确切的类型。

这应该解决标题中关于为什么强制转换在普通接口上不起作用的问题。至于“你应该怎么做”,如果你保证你的接口只输出泛型参数类型的东西并且从不将它们作为输入,你可以通过使接口协变来使其工作,正如其他人所建议的那样。

【讨论】:

    最近更新 更多