目标:通用枚举类型与返回时的类型相同。

注意:输入类型时可以使用,但是我不明白为什么不能推断出它们。
List<T>然后返回List<T>IOrderedEnumerable<T>然后返回IOrderedEnumerable<T>
等等

当前方法(仅在输入所有类型时才有效)

public static TEnumerable WithEach<TEnumerable, T>(this TEnumerable items, Action<T> action)
where TEnumerable : IEnumerable<T>
{
    foreach (var item in items) action.Invoke(item);
    return items;
}

仅示例
var list = new List<int>(); //TODO: Mock random values
list.WithEach(x => Console.WriteLine(x)) //Here WithEach ideally returns List<int> following orignal type List<int>
    .OrderBy(x => x)
    .WithEach(x => Console.WriteLine(x)); //Here WithEach ideally returns IOrderedEnumerable<int> following OrderBy

使它起作用
var list = new List<int>(); //TODO: Mock random values
list.WithEach<List<int>, int>(x => Console.WriteLine(x))
    .OrderBy(x => x)
    .WithEach<IOrderedEnumerable<int>, int>(x => Console.WriteLine(x));

我所缺少的是,尽管where过滤器确实使类型准确,但C#不能推断类型。我了解您为什么不向方法提供全部或不提供泛型类型,所以请不要将我指向这些答案。

编辑:如果我不能推断类型;那我怎样才能使它更优雅呢?

最佳答案

C#中的类型推断非常复杂-只是一次,我不会制定规范来尝试逐步完成它,因为我知道它会变得多么可怕。

我相信问题是参数/参数组合都不给编译器足够的信息来推断T:

  • TEnumerable items参数没有提及T,因此尽管有类型约束
  • ,它也不能用于推断T
  • Action<T>参数会很好,但是编译器无法基于您提供的lamtda表达式进行推断

  • 我想不出对方法签名的一个好的更改,它可以使您的第一个代码完全起作用-但您可以通过在lambda表达式中指定参数类型来稍微改变调用该方法的方式以使其起作用。
    var list = new List<int>();
    list.WithEach((int x) => Console.WriteLine(x++))
        .OrderBy(x => x)
        .WithEach((int x) => Console.WriteLine(x));
    

    缺点是,它当然不适用于匿名类型。

    一种不利的解决方法是一个非常可怕的方法,但是它使您可以在需要时通过参数来表示T的类型。您将方法签名更改为:
    public static TEnumerable WithEach<TEnumerable, T>(
        this TEnumerable items,
        Action<T> action,
        T ignored = default(T))
    

    如果要使用某些匿名类型的列表来调用该方法,则可以编写:
    list.WithEach(x => Console.WriteLine(x.Name), new { Name = "", Value = 10 });
    

    ...最终参数将与匿名类型匹配的位置。这将允许通过最后一个参数而不是第二个参数来推断T的类型。当然,您可以将其用于其他类型,但我可能会坚持将其用于匿名类型。

    这是一个非常可怕的骇客,我不认为我会真正使用它,但是如果您真的需要使用匿名类型,那就可以了。

    关于c# - 如何返回<TEnumerable,T> : where TEnumerable:IEnumerable<T>,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53620392/

    10-09 05:56