拼合的IEnumerable<&IEnumerable的LT;>取代;了解泛型 [英] Flatten IEnumerable<IEnumerable<>>; understanding generics

查看:108
本文介绍了拼合的IEnumerable<&IEnumerable的LT;>取代;了解泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了这个扩展方法(编译):

I wrote this extension method (which compiles):

public static IEnumerable<J> Flatten<T, J>(this IEnumerable<T> @this) 
                                           where T : IEnumerable<J>
{
    foreach (T t in @this)
        foreach (J j in t)
            yield return j;
}



下面的代码将导致编译时错误(没有找到合适的方法),< ?STRONG>为什么

IEnumerable<IEnumerable<int>> foo = new int[2][];
var bar = foo.Flatten();

如果我实现扩展类似下面,我没有得到任何编译时错误:

If I implement the extension like below, I get no compile time error:

public static IEnumerable<J> Flatten<J>(this IEnumerable<IEnumerable<J>> @this)
{
    foreach (IEnumerable<J> js in @this)
        foreach (J j in js)
            yield return j;
}

修改(2):这个问题我考虑回答,但它提出了关于重载决议和类型的限制另一个问题。这个问题我放在这里:为什么不输入方法签名的制约部分

Edit(2): This question I consider answered, but it raised another question regarding overload resolution and type constraints. This question I put here: Why aren't type constraints part of the method signature?

推荐答案

首先,你不需要平展();该方法已经存在,被称为的SelectMany()。您可以使用它是这样的:

First, you don't need Flatten(); that method already exists, and is called SelectMany(). You can use it like this:

IEnumerable<IEnumerable<int>> foo = new [] { new[] {1, 2}, new[] {3, 4} };
var bar = foo.SelectMany(x => x); // bar is {1, 2, 3, 4}



二,你的第一次尝试没有工作,因为通用的类型推断的作品只是基于参数的方法,该方法不相关的泛型约束。由于没有直接使用Ĵ泛型参数没有参数,类型推理引擎无法猜出Ĵ应可以了,因此不认为你的方法是一个人选。

Second, your first attempt doesn't work because generic type inference works only based on the arguments to the method, not generic constraints associated with the method. Since there is no argument that directly uses the J generic parameter, the type inference engine can't guess what J should be, and thus doesn't think that your method is a candidate.

这是有启发性的,看看的SelectMany()解决了这个:它需要一个额外的 Func键< TSource,TResult> 参数。允许类型推理引擎来确定这两种通用的类型,因为它们都是可仅基于所提供的该方法的参数。

It's edifying to see how SelectMany() gets around this: it requires an additional Func<TSource, TResult> argument. That allows the type inference engine to determine both generic types, since they are both available based solely on the arguments provided to the method.

这篇关于拼合的IEnumerable&LT;&IEnumerable的LT;&GT;取代;了解泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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