【问题标题】:C# foreach iterator isn't traversing my List in orderC# foreach 迭代器没有按顺序遍历我的列表
【发布时间】:2013-11-20 18:52:07
【问题描述】:

我是 C# 新手,我想知道是否有人可以解释为什么列表没有在 foreach 循环中按顺序打印出来?我还注意到,如果您在监视窗口中查看卡片,.ToList() 会更改卡片的顺序。为什么会这样?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CardShuffle
{
    class Program
    {
        static void Main(string[] args)
        {
            var r = new Random();
            var cards = Enumerable.Range(0, 51);
            var shuffledcards = cards.OrderBy(a => r.Next(1000));
            var aList = shuffledcards.ToList();

            foreach( int card in aList)
            {
                Console.WriteLine("Card {0} is {1}.", card, aList[card]);
            }
            Console.WriteLine();

            for (int card = 0; card < aList.Count; ++card )
            {
                Console.WriteLine("Card {0} is {1}.", card, aList[card]);
            }
            Console.ReadKey();
        }
    }
}

【问题讨论】:

  • 你想要的顺序是什么?你的列表应该有一个随机的顺序。
  • 您是根据随机数订购的
  • @KingKing 我认为这应该是随机的,因为他只是用var shuffledcards = cards.OrderBy(a =&gt; r.Next(1000));“洗牌”了牌
  • 他的问题是 for 循环和 foreach 产生不同的打印输出。这已被多次询问和回答...stackoverflow.com/questions/1790245/…
  • 你的 foreach 循环是错误的。

标签: c#


【解决方案1】:

你的 foreach 中有一个错误;

foreach( int card in aList)
{
    Console.WriteLine("Card {0} is {1}.", card, aList[card]);
}

card 不是索引,而是值本身。因此,您正在打印值(作为卡号),然后随机访问该索引处的任何内容并将其显示为值。您应该使用计数器来显示卡号并使用card 替换{1}

int i = 0;
foreach( int card in aList)
{
     Console.WriteLine("Card {0} is {1}.", i, card);
     i++;
}

【讨论】:

  • 我认为实际上这里的cardaList 的索引之一,因为源列表使用Enumerable.Range(0,51)
  • @KingKing 那些整数只是列表的数据;它们似乎实际上并不打算成为任何东西的索引。
  • @Servy 它不应该这样使用,但它是合法的并且运行正常。你的意思是它会抛出一些异常吗?我刚刚谈到了值,OP 的源列表意味着索引i 处的值将具有值i。这意味着list[list[i]] = i
  • @KingKing OP令人困惑的根源是他选择使用整数列表来测试洗牌,并且他在是否拥有项目或项目本身的索引之间感到困惑,因为索引和值都是int。例如,如果这些值是字符串,则会导致编译时错误。事实上,它只会导致无意义的代码。由于项目或多或少是打乱的,在任何给定值的索引处查找项目或多或少是一个随机项目,这就是为什么它看起来像一个不同的随机排序。
  • 是的 @Servy 的最后一篇文章是准确的。由于一些巧合,OP 认为该列表以不同的顺序打印。就像 Servy 所说,如果集合中有卡片名称的字符串而不是整数,则会导致编译时错误。如果集合中的值不是 0-51,那么他会在运行时得到 IndexOutOfRange 异常。
【解决方案2】:

假设你有

List<int> aList = new List<int>();
aList.Add(1);
aList.Add(5);
aList.Add(10);
aList.Add(20);

你正在尝试做

foreach( int card in aList)
   {
      Console.WriteLine("Card {0} is {1}.", card, aList[card]);
   }

您实际上正在尝试访问数组的随机元素,因为在我的情况下,在第二个循环中它将访问数组的第五个元素而不是第二个元素,因此如果您想要正确的,则需要运行 for 循环结果。

【讨论】:

  • C# 中没有 new List {...} 这样的东西。请更正您的代码。
  • 是的...抱歉,刚刚做了
  • @HighCore 对我来说它看起来像 List&lt;T&gt; 的静态初始化伪代码,ofc 它不会编译,但我知道他要去哪里。我的回答有问题的原因:)
  • @Stanislav 只是想指出你可以拥有List&lt;int&gt; aList = new List&lt;int&gt;() { 1, 5, 10, 20 };,它会编译并运行。
  • 其实我的答案是基于简单的伪示例对问题的解释:)
【解决方案3】:

在 foreach 循环中,您使用值作为索引来编写卡片。在 for 循环中,您根据索引按顺序编写卡片。

【讨论】:

    【解决方案4】:

    您的foreach 循环逻辑错误。你正在做的是从aList 集合中获取项目,然后将它们用作索引以获取aList 集合中的另一个元素。这就是你得到这种输出的原因。

    要从 foreach 获得与 for 循环相同的输出,请尝试:

    foreach (var item in aList.Select((c, i) => new { card = c, index = i }))
    {
        Console.WriteLine("Card {0} is {1}.", item.index, item.card);
    }
    

    【讨论】:

      【解决方案5】:

      您的 foreach 循环不正确。试试这个

      int counter = 0;
      foreach( int card in aList)
      {
          Console.WriteLine("Card {0} is {1}", counter , card);
          counter++;
      }
      

      【讨论】:

        猜你喜欢
        • 2015-09-18
        • 2016-09-03
        • 1970-01-01
        • 2011-02-28
        • 1970-01-01
        • 2017-07-29
        • 2013-07-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多