0

我想编写一个扩展方法(以流畅的语法使用它),以便如果序列是:

List< int> lst  = new List< int>(){1,2,3 };

我想重复 3 次(例如)。所以输出将是 123123123

我写了这个:

 public static  IEnumerable<TSource>  MyRepeat<TSource>(this IEnumerable<TSource>  source,int n)
    {
         return    Enumerable.Repeat(source,n).SelectMany(f=>f);
    }

现在我可以这样做了:

  lst.MyRepeat(3)

输出 :

在此处输入图像描述

问题 :

我不应该在扩展方法中使用 Yield 吗?我试过yield return 了,但它在这里不起作用。为什么会这样,我应该使用它。

编辑

在 Ant 的回答之后,我将其更改为:

public static  IEnumerable<TSource>  MyRepeat<TSource>(this IEnumerable<TSource>  source,int n)
    {
        var k=Enumerable.Repeat(source,n).SelectMany(f=>f);
        
                foreach (var element in k)
                {
                    yield   return    element;
                }
    }

但是有什么区别吗?

4

2 回答 2

3

这是因为以下已返回IEnumerable:

Enumerable.Repeat(source,n).SelectMany(f=>f);

当您使用yield关键字时,您指定对该方法的给定迭代将返回以下内容。因此,您实际上是在说“每次迭代都会产生一个IEnumerable<TSource>”,而实际上,对返回 an 的方法的每次迭代IEnumerable<TSource>都应该产生一个TSource

因此,您的错误 - 当您迭代时MyRepeat,您应该返回 aTSource但是因为您正在尝试yielda IEnumerable,您实际上是在尝试IEnumerable每次迭代中返回 an而不是返回单个元素。

您的编辑应该可以工作,但有点毫无意义 - 如果您只是直接返回 IEnumerable,它不会被枚举,直到您迭代它(或调用ToList或其他东西)。在您的第一个示例中,SelectMany(或其嵌套方法之一)将已经在 using yield,这意味着 theyield已经存在,它只是隐含在您的方法中。

于 2013-09-15T14:25:40.310 回答
2

Ant P 的回答当然是正确的。

如果您正在构建自己返回的可枚举,而不是依赖 SelectMany,您将使用 yield。例如:

public static IEnumerable<T> Repeat<T>(this IEnumberable<T> items, int repeat)
{
    for (int i = 0; i < repeat; ++i)
        foreach(T item in items)
            yield return item;
}

你产生的东西是序列的一个元素。该代码是用于生成产生元素序列的指令。

于 2013-09-15T15:13:28.467 回答