c# – 为什么协变隐式强制转换会忽略泛型约束?

static IEnumerable<U> DoSomething<T,U>(IEnumerable<T> a)
    where T : U
{
    // Works,compiler can compile-time statically cast
    // T as U.
    T testA = default(T);
    U testB = testA;

    // And the following works,though:
    IEnumerable<string> test2A = null;
    IEnumerable<object> test2B = test2A;

    // Doesn’t work. Compiler cannot compile-time statically
    // cast IEnumerable<T> to IEnumerable<U> even though it is
    // out and T is U.
    return a;
}

我有代码,能够执行这种类型的隐式转换将节省我写很多样板接口实现代码.
这似乎是协方差应该有助于的那种事情.
但是我总是在返回时得到这个错误;以上行:

error CS0266: Cannot implicitly convert type ‘System.Collections.Generic.IEnumerable<T>’ to ‘System.Collections.Generic.IEnumerable<U>’. An explicit conversion exists (are you missing a cast?)

为什么会这样,有没有办法解决这个问题而不做像选择o中的o返回那样的事情?

解决方法

当弄乱我的最小repro并阅读类似但无关的问题 about interface casting时,我意识到以下编译:
static IEnumerable<U> DoSomethingElse<T,U>(IEnumerable<T> a)
    where T : class,U
{
    // Works! Ridik!
    return a;
}

并且以下失败并显示相同的错误消息:

static void Blah()
{
    // Fails for I bet the same reason that DoSomething{T,U} fails:
    IEnumerable<int> a = null;
    IEnumerable<object> b = a;
}

error CS0266: Cannot implicitly convert type ‘System.Collections.Generic.IEnumerable<int>’ to ‘System.Collections.Generic.IEnumerable<object>’. An explicit conversion exists (are you missing a cast?)

所以这似乎与.net如何将某些类型的赋值限制为引用类型有关,因为在这些情况下装箱会是错误的(例如,您可能会假设引用类型并且实际上正在处理值类型的副本)或者在运行时很难/不可能实现(给定一个IEnumerable< int>你必须实现一个包装适配类.好吧,这听起来好像.net不能/不应该在运行时尝试为你做).我认为它是一种情况,其中.net允许指针式多态,就其本质而言,它与值类型的概念不兼容.

因此,对于我的情况,我不需要在我的API中支持值类型,并且添加类约束会使一切变得神奇!

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...