天道酬勤,学无止境

C#-foreach循环的每次迭代都会调用函数吗? [复制](C# - Does function get called for each iteration of a foreach loop? [duplicate])

问题

可能重复:
遍历函数结果时,foreach如何工作?

如果我具有类似以下的功能-将在foreach循环中为每次迭代调用ReturnParts()还是仅一次调用它?

private void PrintParts()
{
     foreach(string part in ReturnParts())
     {
         // Do Something or other. 
     }
}

private string[] ReturnParts()
{
     // Build up and return an array. 
}
回答1

它只会被调用一次。

PS多次调用将毫无意义。 如果您希望每次结果都不同,则可以每次重新调用它。 您将如何遍历不断变化的集合?

回答2

您可以通过在函数“ ReturnParts”上放置一个断点来自己确定,如果每次迭代命中了多次,则可以。

回答3

它只会被调用一次。

foreach循环等效于以下代码:

IEnumerable<string> enumerator = (collection).GetEnumerator();
try {
   while (enumerator.MoveNext()) {
      string part = (string)enumerator.Current;

      // Do Something or other. 

   }
} finally {
   IDisposable disposable = enumerator as System.IDisposable;
   if (disposable != null) disposable.Dispose();
}
回答4

在想知道几周前for,foreach,while和goto之间的区别时,我写下了这个测试代码。 所有这些方法都将编译为相同的IL(foreach版本中的变量名称除外)。在调试模式下,一些NOP语句将位于不同的位置。

static void @for<T>(IEnumerable<T> input)
{
    T item;
    using (var e = input.GetEnumerator())
        for (; e.MoveNext(); )
        {
            item = e.Current;
            Console.WriteLine(item);
        }
}
static void @foreach<T>(IEnumerable<T> input)
{
    foreach (var item in input)
        Console.WriteLine(item);
}
static void @while<T>(IEnumerable<T> input)
{
    T item;
    using (var e = input.GetEnumerator())
        while (e.MoveNext())
        {
            item = e.Current;
            Console.WriteLine(item);
        }
}
static void @goto<T>(IEnumerable<T> input)
{
    T item;
    using (var e = input.GetEnumerator())
    {
        goto check;
    top:
        item = e.Current;
        Console.WriteLine(item);
    check:
        if (e.MoveNext())
            goto top;
    }
}
static void @gotoTry<T>(IEnumerable<T> input)
{
    T item;
    var e = input.GetEnumerator();
    try
    {
        goto check;
    top:
        item = e.Current;
        Console.WriteLine(item);
    check:
        if (e.MoveNext())
            goto top;
    }
    finally
    {
        if (e != null)
            e.Dispose();
    }
}

根据@Eric的评论...

我已经使用通用数组扩展forwhile ,'goto'和foreach 。 现在, for each语句看起来都将索引器用于数组。 对象数组和字符串以类似的方式扩展。 对象将删除在调用Console方法之前发生的装箱操作。WriteLine和Strings分别将T itemT[] copy...替换为char itemstring copy... 请注意,由于不再使用一次性枚举器,因此不再需要关键部分。

static void @for<T>(T[] input)
{
    T item;
    T[] copy = input;
    for (int i = 0; i < copy.Length; i++)
    {
        item = copy[i];
        Console.WriteLine(item);
    }
}
static void @foreach<T>(T[] input)
{
    foreach (var item in input)
        Console.WriteLine(item);
}
static void @while<T>(T[] input)
{
    T item;
    T[] copy = input;
    int i = 0;
    while (i < copy.Length)
    {
        item = copy[i];
        Console.WriteLine(item);
        i++;
    }
}
static void @goto<T>(T[] input)
{
    T item;
    T[] copy = input;
    int i = 0;
    goto check;
top:
    item = copy[i];
    Console.WriteLine(item);
    i++;
check:
    if (i < copy.Length)
        goto top;
}
标签

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 在C#中的循环中捕获的变量(Captured variable in a loop in C#)
    问题 我遇到了一个有关C#的有趣问题。 我有下面的代码。 List<Func<int>> actions = new List<Func<int>>(); int variable = 0; while (variable < 5) { actions.Add(() => variable * 2); ++ variable; } foreach (var act in actions) { Console.WriteLine(act.Invoke()); } 我希望它输出0、2、4、6、8。但是,它实际上输出5个10s。 看来这是由于所有操作都引用了一个捕获的变量。 结果,当它们被调用时,它们都具有相同的输出。 有没有一种方法可以解决此限制,以使每个操作实例都有其自己的捕获变量? 回答1 是的-在循环内获取变量的副本: while (variable < 5) { int copy = variable; actions.Add(() => copy * 2); ++ variable; } 您可以认为它就像C#编译器每次击中变量声明时都创建一个“新”局部变量一样。 实际上,它将创建适当的新闭包对象,并且如果您在多个作用域中引用变量,它会变得复杂(就实现而言),但是它可以起作用: 请注意,此问题更常见的情况是使用for或foreach : for (int i=0; i < 10
  • PHP中FOR与FOREACH的性能(Performance of FOR vs FOREACH in PHP)
    问题 首先,我了解90%的应用程序中的性能差异完全无关紧要,但是我只需要知道哪个是更快的构造即可。 那... 当前网上可用的信息令人困惑。 许多人说foreach不好,但是从技术上讲应该更快,因为它假定可以简化使用迭代器编写数组遍历的过程。 再次被认为是更快的迭代器,但是在PHP中显然还很慢(或者这不是PHP的事情吗?)。 我说的是数组函数:next()prev()reset()等,如果它们甚至是函数,而不是看起来像函数的那些PHP语言功能之一。 稍微缩小一点:我对以大于1的步长遍历数组并不感兴趣(也没有负步长,即反向迭代)。 我也对遍历任意点(长度为0)不感兴趣。 我也没有看到有规律地操纵具有1000个以上键的数组,但是我确实看到一个数组在应用程序的逻辑中被遍历了很多次! 同样对于操作,很大程度上仅是字符串操作和echo'ing。 以下是一些参考站点: http://www.phpbench.com/ http://www.php.lt/benchmark/phpbench.php 我到处听到的是: foreach很慢,因此for / while更快 PHP foreach复制它迭代的数组; 为了更快,您需要使用参考像这样的代码: $key = array_keys($aHash); $size = sizeOf($key); for ($i=0; $i < $size; $i+
  • PHP“ foreach”实际上如何工作?(How does PHP 'foreach' actually work?)
    问题 首先,我要说一下我知道foreach是什么,做什么以及如何使用它。 这个问题关系到它如何在引擎盖下工作,我不希望“这就是使用foreach循环数组的方式”的答案。 很长时间以来,我一直认为foreach与数组本身一起工作。 然后,我发现了很多关于它可以与数组副本一起使用的事实的引用,从那时起,我一直以为这是故事的结尾。 但是我最近对此事进行了讨论,经过一番实验后发现这实际上并非100%正确。 让我表明我的意思。 对于以下测试用例,我们将使用以下数组: $array = array(1, 2, 3, 4, 5); 测试用例1: foreach ($array as $item) { echo "$item\n"; $array[] = $item; } print_r($array); /* Output in loop: 1 2 3 4 5 $array after loop: 1 2 3 4 5 1 2 3 4 5 */ 这清楚地表明,我们不是直接使用源数组-否则循环将永远持续下去,因为我们在循环过程中不断将项目推入数组。 但是只是为了确保是这种情况: 测试案例2: foreach ($array as $key => $item) { $array[$key + 1] = $item + 2; echo "$item\n"; } print_r($array); /*
  • 遍历函数结果时,foreach如何工作?(How does foreach work when looping through function results?)
    问题 假设我有以下代码: foreach(string str in someObj.GetMyStrings()) { // do some stuff } 每次循环迭代时都会调用someObj.GetMyStrings()吗? 最好改为执行以下操作: List<string> myStrings = someObj.GetMyStrings(); foreach(string str in myStrings) { // do some stuff } ? 回答1 该函数仅调用一次,以返回IEnumerator<T> ; 之后,使用MoveNext()方法和Current属性来遍历结果: foreach (Foo f in GetFoos()) { // Do stuff } 在某种程度上等同于: using (IEnumerator<Foo> iterator = GetFoos().GetEnumerator()) { while (iterator.MoveNext()) { Foo f = iterator.Current; // Do stuff } } 请注意,迭代器放置在末尾-这对于从迭代器块释放资源特别重要,例如: public IEnumerable<string> GetLines(string file) { using (TextReader
  • 循环内的JavaScript闭合–简单的实际示例(JavaScript closure inside loops – simple practical example)
    问题 var funcs = []; // let's create 3 functions for (var i = 0; i < 3; i++) { // and store them in funcs funcs[i] = function() { // each should log its value. console.log("My value: " + i); }; } for (var j = 0; j < 3; j++) { // and now let's run each one to see funcs[j](); } 它输出以下内容: 我的价值:3 我的价值:3 我的价值:3 而我希望它输出: 我的值:0 我的价值:1 我的价值:2 当由于使用事件侦听器而导致功能运行延迟时,会发生相同的问题: var buttons = document.getElementsByTagName("button"); // let's create 3 functions for (var i = 0; i < buttons.length; i++) { // as event listeners buttons[i].addEventListener("click", function() { // each should log its value. console
  • C#中的lambda如何在foreach中绑定到枚举器?(How does a lambda in C# bind to the enumerator in a foreach?)
    问题 我只是遇到了最意外的行为。 我敢肯定有一个很好的理由,它能以这种方式工作。 有人可以帮忙解释一下吗? 考虑以下代码: var nums = new int[] { 1, 2, 3, 4 }; var actions = new List<Func<int>>(); foreach (var num in nums) { actions.Add(() => num); } foreach (var num in nums) { var x = num; actions.Add(() => x); } foreach (var action in actions) { Debug.Write(action() + " "); } 输出对我来说有点令人惊讶: 4 4 4 4 1 2 3 4 显然,lambda是如何引用枚举器的。 在foreach的第一个版本中,'num'实际上绑定到'Current'而不是它返回的结果吗? 回答1 这是关于lambda的众所周知的既定行为,尽管对于第一次遇到lambda的人经常会感到惊讶。 根本问题是,您关于lambda是什么的心理模型不太正确。 Lambda是在被调用之前不会运行的函数。 您的闭包将绑定到该lambda实例的引用,而不是值。 当您在最后的foreach循环中执行操作时,这是您第一次真正遵循封闭的引用来查看其内容。 在第一种情况下
  • foreach和map之间有区别吗?(Is there a difference between foreach and map?)
    问题 好的,这更多是计算机科学问题,而不是基于特定语言的问题,但是map操作和foreach操作之间有区别吗? 还是它们只是同一事物的不同名称? 回答1 不同的。 foreach遍历列表,并对每个列表成员应用一些具有副作用的操作(例如,将每个保存到数据库) map遍历一个列表,转换该列表的每个成员,然后返回与转换后的成员大小相同的另一个列表(例如将字符串列表转换为大写字母) 回答2 它们之间的重要区别是map所有结果累加到一个集合中,而foreach返回任何结果。 map通常用于想要通过函数转换元素集合的情况,而foreach只需为每个元素执行一个动作。 回答3 简而言之, foreach用于对元素集合的每个元素进行操作,而map用于将一个集合转换为另一个集合。 foreach和map之间有两个重要区别。 除了可能接受一个元素作为参数外, foreach对它所应用的操作没有概念上的限制。 也就是说,该操作可能什么都不做,可能有副作用,可能返回值或可能不返回值。 foreach关心的只是遍历元素集合,并对每个元素应用操作。 另一方面, map确实对操作有限制:它希望该操作返回一个元素,并且可能还接受一个元素作为参数。 map操作迭代元素的集合,将操作应用于每个元素,最后将操作的每次调用结果存储到另一个集合中。 换句话说, map将一个集合转换为另一个集合。
  • 遍历字母-C#a-caz(Iterating through the Alphabet - C# a-caz)
    问题 我有一个关于字母迭代的问题。 我想有一个以“ a”开始并以“ z”结束的循环。 之后,循环开始于“ aa”并计数为“ az”。 之后,从“ ba”开始直到“ bz”,依此类推... 有人知道解决方案吗? 谢谢 编辑:我忘了我给函数一个字符“ a”,然后该函数必须返回b。 如果您给“ bnc”,则该函数必须返回“ bnd” 回答1 编辑:使其完全符合OP的最新编辑要求 这是最简单的解决方案,并经过测试: static void Main(string[] args) { Console.WriteLine(GetNextBase26("a")); Console.WriteLine(GetNextBase26("bnc")); } private static string GetNextBase26(string a) { return Base26Sequence().SkipWhile(x => x != a).Skip(1).First(); } private static IEnumerable<string> Base26Sequence() { long i = 0L; while (true) yield return Base26Encode(i++); } private static char[] base26Chars =
  • 强制释放PHP中的内存(Force freeing memory in PHP)
    问题 在一个PHP程序中,我依次读取了一堆文件(带有file_get_contents ), gzdecode它们进行json_decode对结果进行json_decode ,分析内容,将其中的大部分扔掉,并在数组中存储大约1%的内容。 不幸的是,每次迭代(我遍历包含文件名的数组)时,似乎都会丢失一些内存(根据memory_get_peak_usage ,每次大约2-10 MB)。 我已经仔细检查了我的代码; 我不在循环中存储不需要的数据(所需数据总体上几乎不超过10MB),但是我经常重写(实际上是数组中的字符串)。 显然,PHP无法正确释放内存,因此会使用越来越多的RAM,直到达到极限为止。 有什么办法可以进行强制垃圾收集吗? 还是至少要找出内存的使用位置? 回答1 它与内存碎片有关。 考虑两个字符串,连接到一个字符串。 必须保留每个原始文档,直到创建输出为止。 输出比任何一个输入都长。 因此,必须进行新的分配以存储这种级联的结果。 原始字符串被释放,但是它们是很小的内存块。 在'str1' . 'str2' . 'str3' . 'str4'的情况下'str1' . 'str2' . 'str3' . 'str4' 'str1' . 'str2' . 'str3' . 'str4' 'str1' . 'str2' . 'str3' . 'str4'您将在每个位置创建多个临时文件
  • Lambda变量捕获循环-这里发生了什么? [复制](Lambda variable capture in loop - what happens here? [duplicate])
    问题 这个问题已经在这里有了答案: 在C#中的循环中捕获的变量(10个答案) 9个月前关闭。 我想尽我所能,这会发生什么? 编译器产生什么样的代码? public static void vc() { var listActions = new List<Action>(); foreach (int i in Enumerable.Range(1, 10)) { listActions.Add(() => Console.WriteLine(i)); } foreach (Action action in listActions) { action(); } } static void Main(string[] args) { vc(); } 输出: 10 10 .. 10 据此,将为每次迭代创建一个新的ActionHelper实例。 因此,在那种情况下,我认为它应该打印1..10。 有人可以给我一些编译器在这里做的伪代码吗? 谢谢。 回答1 在这条线 listActions.Add(() => Console.WriteLine(i)); 捕获变量i ,或者根据需要创建指向该变量的内存位置的指针。 这意味着每个委托都有指向该内存位置的指针。 执行此循环后: foreach (int i in Enumerable.Range(1, 10)) { listActions.Add
  • StartCoroutine /收益率返回模式在Unity中如何真正起作用?(How does StartCoroutine / yield return pattern really work in Unity?)
    问题 我了解协程的原理。 我知道如何获取标准的StartCoroutine / yield return模式以在Unity中的C#中工作,例如,调用通过StartCoroutine返回IEnumerator的方法,并在该方法中执行某些操作,并yield return new WaitForSeconds(1); 等待一秒钟,然后再做其他事情。 我的问题是:幕后到底发生了什么? StartCoroutine真正做什么? WaitForSeconds返回什么IEnumerator ? StartCoroutine如何将控制StartCoroutine返回给被调用方法的“其他”部分? 所有这些如何与Unity的并发模型(其中不使用协程同时进行很多事情)进行交互? 回答1 详细引用的Unity3D协程的常规链接已死。 由于在评论和答案中提到了它,因此我将在此处发布文章的内容。 此内容来自此镜像。 Unity3D协程详细游戏中的许多过程都是在多个框架的过程中进行的。 您已经获得了“密集”过程,例如寻路,该过程在每个帧上都非常努力,但是会分成多个帧,以免对帧率产生太大影响。 您拥有诸如游戏触发器之类的“稀疏”过程,这些过程在大多数帧中都不执行任何操作,但偶尔会被要求执行关键工作。 而且您在两者之间有各种各样的过程。 每当您要创建一个将在多个框架上进行的过程(而无需多线程)时
  • Scala是否具有等效于C#的收益率?(Does Scala have an equivalent to C# yield?)
    问题 我是Scala的新手,据我了解,Scala中的yield不像C#中的yield,它更像select。 Scala是否具有类似于C#的收益率的东西? C#的产量很高,因为它使编写迭代器变得非常容易。 更新:这是来自C#的伪代码示例,我希望能够在Scala中实现: public class Graph<T> { public IEnumerable<T> BreadthFirstIterator() { List<T> currentLevel = new List<T>(); currentLevel.add(_root); while ( currentLevel.count > 0 ) { List<T> nextLevel = new List<T>(); foreach( var node in currentLevel ) { yield return node; nextLevel.addRange( node.Children ); } currentLevel = nextLevel; } } } 该代码使用yield来实现图的迭代广度优先遍历,它返回一个迭代器,以便调用者可以使用常规的for循环遍历图,例如: graph.BreadthFirstIterator().foreach( n => Console.WriteLine( n ) ); 在C#中
  • foreach()是否通过引用进行迭代?(Does foreach() iterate by reference?)
    问题 考虑一下: List<MyClass> obj_list = get_the_list(); foreach( MyClass obj in obj_list ) { obj.property = 42; } obj是对列表中相应对象的引用,以便当我更改属性时,更改一旦在某处构造后将保留在对象实例中? 回答1 是的, obj是对集合中当前对象的引用(假设MyClass实际上是一个类)。 如果您通过引用更改了任何属性,则就像您期望的那样,您也在更改对象。 但是请注意,您不能更改变量obj本身,因为它是迭代变量。 如果尝试,将出现编译错误。 这意味着您不能将其为null,并且如果要迭代值类型,则不能修改任何成员,因为那样会更改值。 C#语言规范的状态(8.8.4) “迭代变量对应于只读局部变量,其范围扩展到嵌入式语句。” 回答2 是的,直到将通用类型从“列表”更改为IEnumerable。 回答3 您在这里问了2个不同的问题,让我们按顺序进行。 foreach循环是否通过引用进行迭代? 如果您的意思与按引用进行循环的C ++相同,则否。 C#没有与C ++相同的局部变量引用,因此不支持这种类型的迭代。 变更会持续存在吗 假设MyClass是引用类型,答案是肯定的。 类是.Net中的引用类型,因此迭代变量是对一个变量的引用,而不是副本。 对于值类型,这不是正确的。 回答4 好吧
  • 每次执行时,lambda表达式都会在堆上创建一个对象吗?(Does a lambda expression create an object on the heap every time it's executed?)
    问题 当我使用Java 8的新语法糖遍历集合时,例如 myStream.forEach(item -> { // do something useful }); 这不等同于下面的“旧语法”代码段吗? myStream.forEach(new Consumer<Item>() { @Override public void accept(Item item) { // do something useful } }); 这是否意味着每次迭代集合时都会在堆上创建一个新的匿名Consumer对象? 这需要多少堆空间? 它对性能有什么影响? 这是否意味着在遍历大型多级数据结构时,我应该宁愿使用旧样式的循环? 回答1 它是等效的但不相同。 简而言之,如果lambda表达式未捕获值,则它将是单例,可在每次调用时重复使用。 行为没有完全指定。 JVM在实现它方面有很大的自由度。 当前,Oracle的JVM为每个lambda表达式创建(至少)一个实例(即不在不同的相同表达式之间共享实例),但为所有不捕获值的表达式创建单例。 您可以阅读此答案以获取更多详细信息。 在那里,我不仅给出了更详细的描述,而且还提供了测试代码以观察当前行为。 Java®语言规范的“ 15.27.4章”对此进行了介绍。 Lambda表达式的运行时评估” 总结: 这些规则旨在通过以下方式为Java编程语言的实现提供灵活性:
  • 为什么R中的循环慢?(Why are loops slow in R?)
    问题 我知道R中的循环很慢,我应该尝试以向量化的方式进行操作。 但为什么? 为什么循环慢而apply快? apply调用了几个子功能-看起来并不快。 更新:很抱歉,这个问题是不恰当的。 我apply量化和apply混淆了。 我的问题应该是 “为什么矢量化更快?” 回答1 出于任何解释语言都较慢的原因,R中的循环很慢:每个操作都会带来很多额外的负担。 查看eval.c中的R_execClosure(这是调用用户定义的函数的函数)。 它大约有100行,可以执行各种操作-创建执行环境,向该环境分配参数,等等。 想想当您在C中调用一个函数(将args推入堆栈,跳转,pop args)时发生的事情少了多少。 所以这就是为什么你喜欢这些时间(如在评论joran指出,这不是实际apply这是速度快,它在内部C环mean说的是快。 apply只是普通的旧R代码里面): A = matrix(as.numeric(1:100000)) 使用循环:0.342秒: system.time({ Sum = 0 for (i in seq_along(A)) { Sum = Sum + A[[i]] } Sum }) 使用sum:不可估量的小: sum(A) 这有点令人不安,因为在渐近状态下,循环与sum一样好; 没有实际的原因,它应该很慢; 每次迭代只会做更多的额外工作。 因此请考虑: # 0.370
  • 循环反向真的更快吗?(Are loops really faster in reverse?)
    问题 我已经听过好几次了。 向后计数时,JavaScript循环真的更快吗? 如果是这样,为什么? 我已经看到了一些测试套件示例,这些示例显示了反向循环更快,但是我找不到关于原因的任何解释! 我假设这是因为循环不再需要在每次检查它是否完成并且每次检查最终数值时都必须求值一个属性。 IE for (var i = count - 1; i >= 0; i--) { // count is only evaluated once and then the comparison is always on 0. } 回答1 不是i--比i++快。 实际上,它们的速度都一样快。 在递增循环中需要花费时间的是,对于每个i ,都要评估数组的大小。 在此循环中: for(var i = array.length; i--;) 声明i时,您只评估一次.length ,而对于此循环 for(var i = 1; i <= array.length; i++) 当您检查i <= array.length时,每次增加i时您就评估.length 。 在大多数情况下,您甚至不必担心这种优化。 回答2 这个人在很多浏览器中比较了javascript中的很多循环。 他还具有一个测试套件,因此您可以自己运行它们。 在所有情况下(除非我在阅读中错过了一个),最快的循环是: var i = arr.length; /
  • 在C#中使用yield return迭代器的目的/优势是什么?(What is the purpose/advantage of using yield return iterators in C#?)
    问题 我见过的所有使用yield return x;的示例yield return x; 只需返回整个列表,就可以以相同的方式完成C#方法中的操作。 在那些情况下,使用yield return语法与返回列表相比有什么好处或优势? 另外,在哪种类型的方案中会使用yield return ,而您不能仅仅返回完整清单? 回答1 But what if you were building a collection yourself? In general, iterators can be used to lazily generate a sequence of objects. For example Enumerable.Range method does not have any kind of collection internally. It just generates the next number on demand. There are many uses to this lazy sequence generation using a state machine. Most of them are covered under functional programming concepts. In my opinion, if you are looking at
  • 有人可以揭开yield关键字的神秘面纱吗?(Can someone demystify the yield keyword?)
    问题 我已经看到yield关键字在Stack Overflow和博客上被大量使用。 我不使用LINQ。 有人可以解释yield关键字吗? 我知道类似的问题也存在。 但是,没有人真正用简单的语言来解释它的用途。 回答1 到目前为止(我见过的)最好的解释是Jon Skeet的书-该章是免费的! 第6章,深入了解C#。 我无法在此处添加未涵盖的所有内容。 然后买书; 您将因此成为更好的C#程序员。 问:为什么我在这里不写更长的答案(从评论中改写);为什么? 简单的。 正如埃里克·利珀特(Eric Lippert)所观察到的(在这里), yield构造(以及它背后的魔力)是C#编译器中最复杂的代码,要在这里简短地进行描述,充其量是幼稚的。 yield太多细微差别,以至于IMO最好引用一个已存在(且完全合格)的资源。 埃里克(Eric)的博客现在有7条关于yield条目(这只是最近的条目)。 我对埃里克·尊重了大量的,但他的博客可能更适合作为“更多信息”的人谁是舒适的主题( yield在这种情况下),因为它通常描述了很多的背景设计考虑。 最好在合理的基础上完成。 (是的,第6章确实下载了;我已验证...) 回答2 yield关键字与返回IEnumerable<T>或IEnumerator<T> ,它使编译器生成一个类,该类实现使用迭代器所需的管道。 例如 public IEnumerator
  • 递归还是迭代?(Recursion or Iteration?)
    问题 如果我们在算法中都可以使用循环而不是递归来实现性能的提高,反之亦然吗? 例如:检查给定的字符串是否是回文。 我已经看到许多程序员使用递归来证明简单的迭代算法何时可以胜任。 编译器在决定使用什么方面起着至关重要的作用吗? 回答1 取决于递归函数是否为尾递归(最后一行是递归调用),递归可能会更昂贵。 尾递归应该由编译器识别,并针对其迭代对等进行优化(同时保持代码中简洁明了的实现)。 我将以最有意义的方式编写该算法,并且对于必须在几个月或几年内维护代码的可怜的傻瓜(无论是您本人还是其他人)最清晰。 如果遇到性能问题,请先对代码进行概要分析,然后再转向迭代实现,然后再进行优化。 您可能需要研究记忆和动态编程。 回答2 循环可以提高程序的性能。 递归可以为您的程序员提高性能。 选择哪种在您的情况下更重要! 回答3 将递归与迭代进行比较就好比将十字螺丝刀与平头螺丝刀进行比较。 在大多数情况下,您可以卸下任何平头的十字头螺钉,但是如果您使用专为该螺钉设计的螺丝刀,那会更容易吗? 某些算法由于其设计方式而适合进行递归(斐波纳契数列,遍历树状结构等)。 递归使算法更简洁,更易于理解(因此可共享和可重用)。 另外,某些递归算法使用“惰性评估”,这使其比迭代兄弟更有效。 这意味着它们仅在需要时进行昂贵的计算,而不是每次循环运行时都进行。 这应该足以让您入门。 我也将为您挖掘一些文章和示例。 链接1
  • 即使MSDN另有建议,为什么Parallel.ForEach比AsParallel()。ForAll()快得多?(Why is Parallel.ForEach much faster then AsParallel().ForAll() even though MSDN suggests otherwise?)
    问题 我一直在做一些调查,以了解如何创建运行在树上的多线程应用程序。 为了找到最佳方法,我创建了一个测试应用程序,该应用程序通过C:\磁盘运行并打开所有目录。 class Program { static void Main(string[] args) { //var startDirectory = @"C:\The folder\RecursiveFolder"; var startDirectory = @"C:\"; var w = Stopwatch.StartNew(); ThisIsARecursiveFunction(startDirectory); Console.WriteLine("Elapsed seconds: " + w.Elapsed.TotalSeconds); Console.ReadKey(); } public static void ThisIsARecursiveFunction(String currentDirectory) { var lastBit = Path.GetFileName(currentDirectory); var depth = currentDirectory.Count(t => t == '\\'); //Console.WriteLine(depth + ": " + currentDirectory)