有没有办法在C#中使用Enumerable.Repeat方法重复执行Func<T, T>?

3

我编写了一个函数,它接受(Func&int N)并重复执行Func N次并返回结果。

public IEnumerable<T> MyFunction(Func<T, T> function, int iteration)
{

}

是否有办法使用Enumerable.Repeat重复执行一个函数?

public IEnumerable<T> MyFunction(Func<T, T> function, int iteration)
{
    yield return Enumerable.Repeat<T>(function.Invoke(), iteration);
}

我尝试运行上述代码,但该函数只运行一次。

你能给我展示一下 Enumerable.Repeat 可以运行一个 Action 多次的文档吗?我所能找到的唯一文档是说它会返回一个指定次数的某种值的可枚举对象。 - Heretic Monkey
使用以下代码:Enumerable.Repeat<Action>(() => { Console.WriteLine("Hello World"); },10).ToList().ForEach(f => f.Invoke()); @HereticMonkey - Saleh Bagheri
1
那不是在执行动作,而是定义了10个准备好被调用的动作(并且在你的“ForEach”中稍后进行),因此您也不需要在其中使用ToList - Heretic Monkey
1
请编辑您的问题,以一种实际的方式使用它。目前看起来并不是很实用;使用循环可以用更少的代码完成相同的任务,并且对后来的读者更有意义。 - Heretic Monkey
4
你可以使用Repeat构建一些重复函数的奇怪东西,所以从技术上讲,答案是肯定的。 Repeat可以重复任何内容。但这样做会变得异常复杂。下一个开发人员可能会感到困惑,可能会使用循环重新编写它,然后担心有更复杂的情况发生,而他们只是错过了它。当他们意识到他们没有错过任何东西时,他们会感到失落,并想:“哦,不,我还会在这里找到什么别的吗?” - Scott Hannen
显示剩余3条评论
3个回答

4
为什么不直接在循环中调用该方法:
for(int i = 0; i < iteration; i++)
    yield return function(myTInstance);

或者在 Linq 语句中:

return Enumerable.Range(0, iteration).Select(x => function(MyTInstance));

谢谢,@HimBromBeere!但我正在寻找一种优雅的方法来重复执行一个函数。 - Saleh Bagheri
2
@SalehBagheri 我不明白你想要什么。这段代码正好做了你想要的事情:执行一个方法多次,并将所有方法的返回值聚合到一个集合中。 - MakePeaceGreatAgain
@HimBromBeere 我认为他应该先学习什么是钉子,什么是工具,什么是返回类型,然后再开始使用 LINQ 锤子。否则他会在脑海中变得混乱,并成为“复制粘贴程序员” ;) - Kamil

3
有一种方法,尽管我不确定它证明了什么。
static public IEnumerable<T> MyFunction<T>(Func<T> function, int iteration)
{
    return Enumerable.Repeat(function, iteration).Select( x => x() );
}

public static void Main()
{
    int n = 0;

    foreach (var i in MyFunction(() => n++, 10)) Console.WriteLine(i);
}

出于某种原因,更常见的做法是这样:

    return Enumerable.Range(0, iteration).Select( x => function() );

我经常在Stackoverflow上看到后一种结构。
输出:
0
1
2
3
4
5
6
7
8
9

@John-wu 你正在使用LINQ和lambda表达式来回答一个不了解枚举器和yield关键字的人提出的问题。对于初学者来说,不使用LINQ和lambda的答案会更容易理解。 - Kamil
@Kamil,我只是问了一个关于如何在不使用ForForEach或其他循环关键字的情况下重复执行函数的问题。你有什么想法吗?如果没有,请不要评判我的知识! - Saleh Bagheri
1
@Kamil 我认为这个答案很有帮助,因为它展示了正确、惯用的方法,以及可能是唯一使用 Enumerable.Repeat() 的方式,即与 LINQ 结合生成有用的序列。老实说,我不知道还能用它做什么。 - John Wu
这里没有人在评判任何人。但是你需要明白,LINQ 内部无论如何都会调用 foreach,只是将其隐藏了起来。因此,myCollection.Select(x => ...)foreach(var x in myCollection) ... 之间唯一的区别就是 语法。然而,这两个语句都会执行完全相同的操作。 - MakePeaceGreatAgain

0
// this is wrong

public IEnumerable<T> MyFunction(Func<T, T> function, int iteration)
{
    yield return Enumerable.Repeat<T>(function.Invoke(), iteration);
}

你在单个yield语句中返回了Repeat(...)返回的整个IEnumerable集合(没有意义)。
你方法的另一个问题是返回类型。如果你想返回Func对象,必须将方法的返回类型从IEnumerable替换为Func。
Enumerable.Repeat(...)方法的目的是创建一个包含给定对象的N个实例的集合,并返回整个集合。
如果你想要逐个返回对象,则必须逐个返回这些对象。
我认为你需要这样做: (为了更好地理解,我没有使用LINQ和lambda表达式)
public Func<T,T> MyFunction(Func<T, T> function, int iteration)
{
    // create a collection with `N = interation` items
    IEnumerable<Func<T,T>> items = Enumerable.Repeat<T>(function.Invoke(), iteration);

    // return items
    foreach(Func<T,T> item in items)
    {
        yield return item;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接