如何返回< TEnumerable,T> :其中TEnumerable:IEnumerable< T> [英] How can I return <TEnumerable, T> : where TEnumerable:IEnumerable<T>

查看:105
本文介绍了如何返回< TEnumerable,T> :其中TEnumerable:IEnumerable< T>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标:通用枚举类型在返回时是相同类型.

注意:输入类型时此方法有效,但我不明白为什么不能推断出它们.

List<T>然后返回List<T>

IOrderedEnumerable<T>然后返回IOrderedEnumerable<T>

ETC

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

Current method (works only if all types are entered)

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#不能推断类型.我了解您为什么不为方法提供全部或不提供泛型类型,所以请不要将我指向这些答案.

What I'm missing is why C# can't infer the types although the where filter does make the types accurate. I understand why you either supply all or none generic types to methods so please do not point me to those answers.

如果无法推断类型,请输入以下内容:那我怎样才能使它更优雅呢?

If I can't infer the types; then how can I make this more elegant?

推荐答案

C#中的类型推断非常复杂[em] -仅此一次,我不打算尝试使用该规范通过它,因为我知道它会变得多么可怕.

Type inference in C# is very complicated - just for once, I'm not going to get the spec out to try to step through it, because I'm aware of just how horrible it can become.

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

I believe the problem is that neither of the parameter/argument combinations gives the compiler enough information to infer T:

  • TEnumerable items参数未提及T,因此尽管存在类型约束,它也不能用于推断T
  • Action<T>参数很好,但是编译器无法基于您提供的lambda表达式进行推断
  • The TEnumerable items parameter doesn't mention T, so it isn't used to infer T, despite the type constraint
  • The Action<T> parameter would be fine, but the compiler can't make an inference based on the lambda expression you're providing

我想不出对方法签名的一个很好的改变,以使完全成为您的第一个代码,但是您可以稍微改变一下方法的调用方式通过在lambda表达式中指定参数类型来使其工作:

I can't think of a good change to the method signature that would make exactly your first code work - but you can change how you invoke the method just a little to make it work, by specifying the parameter type in the lambda expression:

var list = new List<int>();
list.WithEach((int x) => Console.WriteLine(x++))
    .OrderBy(x => x) 
    .WithEach((int x) => Console.WriteLine(x));

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

The downside of that is that it won't work with anonymous types, of course.

该缺点的一种解决方法非常可怕,但是它使您可以在需要时通过参数来表示T的类型.您将方法签名更改为:

One workaround for that downside is a pretty horrible one, but it lets you express the type of T via a parameter instead, when you need to. You change the method signature to:

public static TEnumerable WithEach<TEnumerable, T>(
    this TEnumerable items,
    Action<T> action,
    T ignored = default(T))

如果要使用某种匿名类型的列表来调用该方法,则可以编写:

If you wanted to call the method with a list of some anonymous type, you could write:

list.WithEach(x => Console.WriteLine(x.Name), new { Name = "", Value = 10 });

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

... where the final argument would match the anonymous type. That will allow the type of T to be inferred by the final parameter instead of the second one. You can use that for other types of course, but I'd probably stick to using it for anonymous types instead.

这都是一个非常可怕的hack,我不认为我会实际使用它,但是如果您真的需要使用匿名类型,那就可以了.

That's all a pretty horrible hack, and I don't think I'd actually use it, but if you really, really need this to work with anonymous types, it would cope.

这篇关于如何返回&lt; TEnumerable,T&gt; :其中TEnumerable:IEnumerable&lt; T&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆