为什么不接受 IEnumerable(of T) 作为扩展方法接收器

本文关键字:扩展 方法 接收器 不接受 IEnumerable of 为什么 | 更新日期: 2023-09-27 18:32:28

在代码之前完成问题

为什么不接受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<T>'不包含'ToInfoObjects'的定义,最好的扩展方法重载'Extensions.ToInfoObjects(IEnumerable<ITest>)'需要类型为'IEnumerable<ITest>'的接收器

为什么会这样?ToInfoObjects扩展方法的接收方是一个IEnumerable<T>,并且通过泛型类型约束,T必须实现ITest

那么为什么不接受接收器呢?我的猜测是IEnumerable<T>的协方差,但我不确定。

如果我更改ToInfoObjects以接收IEnumerable<T> where T : ITest,那么一切都很好。

为什么不接受 IEnumerable(of T) 作为扩展方法接收器

考虑一下:

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 中将约束添加到T class,则代码将编译。

您可以执行以下操作:

    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的通知。