【问题标题】:Why do covariant implicit casts ignore generic constraints?为什么协变隐式强制转换忽略泛型约束?
【发布时间】:2016-08-23 22:23:11
【问题描述】:
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;
}

我有代码,能够执行这种类型的隐式转换将节省我编写大量样板接口实现代码。 这似乎是协方差应该提供帮助的那种事情。 但我总是在上面的return a; 行收到此错误:

错误 CS0266:无法将类型“System.Collections.Generic.IEnumerable”隐式转换为“System.Collections.Generic.IEnumerable”。存在显式转换(您是否缺少演员表?)

为什么会这样?有没有办法在不执行return from o in a select o; 之类的操作的情况下解决这个问题?

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    在处理我的最小复制并阅读类似但不相关的问题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;
    }
    

    错误 CS0266:无法将类型“System.Collections.Generic.IEnumerable”隐式转换为“System.Collections.Generic.IEnumerable”。存在显式转换(您是否缺少演员表?)

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

    所以,就我而言,我不需要在我的 API 中支持值类型,添加 class 约束让一切变得神奇!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-30
      • 1970-01-01
      • 1970-01-01
      • 2011-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-23
      相关资源
      最近更新 更多