【问题标题】:Why is IEnumerable(of T) not accepted as extension method receiver为什么不接受 IEnumerable(of T) 作为扩展方法接收器
【发布时间】:2016-01-29 09:39:17
【问题描述】:

在代码前完成问题

为什么IEnumerable<T> where T : ITest 不被接受为期望this IEnumerable<ITest> 的扩展方法的接收者?

现在是代码

我有三种类型:

public interface ITest { }
public class Element : ITest { }
public class ElementInfo : ITest { }

还有两种扩展方法:

public static class Extensions
{
    public static IEnumerable<ElementInfo> Method<T>(
        this IEnumerable<T> collection) 
        where T : ITest
    {
→        return collection.ToInfoObjects();
    }

    public static IEnumerable<ElementInfo> ToInfoObjects(
        this IEnumerable<ITest> collection)
    {
        return collection.Select(item => new ElementInfo());
    }
}

我得到的编译器错误(在标记线上):

CS1929 : 'IEnumerable&lt;T&gt;' 不包含'ToInfoObjects' 的定义,并且最佳扩展方法重载'Extensions.ToInfoObjects(IEnumerable&lt;ITest&gt;)' 需要'IEnumerable&lt;ITest&gt;' 类型的接收器

为什么会这样? ToInfoObjects 扩展方法的接收者是IEnumerable&lt;T&gt;,并且通过泛型类型约束,T 必须实现ITest

为什么接收方不被接受?我的猜测是IEnumerable&lt;T&gt; 的协方差,但我不确定。

如果我将ToInfoObjects 更改为接收IEnumerable&lt;T&gt; where T : ITest,那么一切正常。

【问题讨论】:

    标签: c# .net generics extension-methods type-inference


    【解决方案1】:

    考虑一下:

    public struct ValueElement : ITest { }
    

    还有这个:

    IEnumerable<ValueElement> collection = ...
    collection.Method(); //OK, ValueElement implement ITest, as required.
    collection.ToInfoObjects() //Error, IEnumerable<ValueElement> is not IEnumerable<ITest>
                               //variance does not work with value types.
    

    所以不是Method 允许的每种类型也允许ToInfoObjects。如果在Method 中将class 约束添加到T,那么您的代码将编译。

    【讨论】:

    • 既然你已经说过了,我觉得这很明显。 T 可能是值类型,当然它不起作用。非常感谢。作为后续,我想link to the reason 为什么 co(ntra)variance 不适用于值类型。
    【解决方案2】:

    您可以执行以下操作:

        public static IEnumerable<ElementInfo> Method<T>(
            this IEnumerable<T> collection)
            where T : ITest
        {
            return collection.ToInfoObjects();
        }
    
        public static IEnumerable<ElementInfo> ToInfoObjects<T>(
            this IEnumerable<T> collection)
        {
            return collection.Select(item => new ElementInfo());
        }
    

    关于 ToInfoObjects 的通知。

    【讨论】:

    • 感谢您的建议,但我知道我可以做些什么来解决这个问题,更重要的是,我已经在原帖中写了。我想知道问题发生的原因,而不是如何解决。
    • @KornelijePetak 哦,很抱歉没有对您的问题给予足够的重视。
    猜你喜欢
    • 1970-01-01
    • 2016-01-12
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多