何时使用每种类型的循环?

sup*_*er9 4 c# loops

我正在学习编程的基础知识(C#),但我认为这个问题本质上是通用的.

什么是一些简单的实际情况,使自己更接近特定类型的循环?

whilefor循环似乎非常相似,并且有解决两者之间的差异几个SO问题.怎么样foreach?根据我的基本理解,它似乎应该能够在foreach循环中完成for循环所做的所有事情.

Col*_*kay 9

哪种方式最适合代码可读性.换句话说,使用最符合情况的那个.

while:当您有一个需要在每个循环开始时检查的条件.例如while(!file.EndOfFile) { }

for:当你有一个索引或计数器时,你在每个循环上递增.for (int i = 0; i<array.Length; i++) { }.从本质上讲,你正在循环的东西是一个可索引的集合,数组,列表等.

foreach:当您循环遍历一组对象或其他Enumerable时.在这种情况下,您可能不知道(或关心)集合的大小,或者集合不是基于索引的(例如,一组对象).一般来说,当我对某些东西或任何其他退出条件的索引不感兴趣时​​,我发现foreach循环是最可读的.

无论如何,这些都是我的一般经验法则.


Evr*_*glu 5

foreach和for

foreach环可与IEnumerator的,当for循环带的索引(在工作object myObject = myListOfObjects[i],i是索引).

两者之间有很大的不同:

  • 索引可以根据列表中的位置直接访问任何对象.

  • 枚举器只能访问列表的第一个元素,然后移动到下一个元素(如msdn中的上一个链接所述).它不能直接访问元素,只需知道列表中元素的索引即可.

因此,调查员可能看起来不那么强大,但是:

  • 您并不总是知道组中元素的位置,因为所有组都没有排序/索引.
  • 你并不总是知道列表中的元素数量(想想链接列表).
  • 即使它是有序的,列表的索引访问也可以在内部基于枚举器,这意味着每次按位置访问元素时,您实际上可能实际枚举列表中的所有元素,直到您想要的元素为止.
  • 索引并不总是数字.想想字典.

所以实际上foreach循环和底层使用的强大之IEnumerator处在于它适用于任何实现的类型IEnumerable(实现IEnumerable只意味着你提供了一个返回枚举器的方法).列表,数组,字典和所有其他组类型都实现IEnumerable.而且你可以确定他们拥有的枚举器是最好的:你找不到最快的方式来浏览列表.

因此,for循环通常可以被视为专用foreach循环:

public void GoThrough(List<object> myList)
{
    for (int i=0; i<myList.Count; i++)
    {
        MessageBox.Show(myList[i].ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

完全等同于:

public void GoThrough(List<object> myList)
{
    foreach (object item in myList)
    {
        MessageBox.Show(item.ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

一般因为有一个明显的情况for需要循环:当你需要对象的索引(即列表中的位置)时,出于某种原因(比如显示它).您将最终意识到只有在您执行良好的.NET编程时才会出现这种情况,并且这foreach应该是您在一组元素上循环的默认候选者.

现在继续比较foreach循环,它确实只是一个眼睛糖果特定的循环:

public void GoThrough(IEnumerable myEnumerable)
{
    foreach (object obj in myEnumerable)
    {
        MessageBox.Show(obj.ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

完全等同于:

public void GoThrough(IEnumerable myEnumerable)
{
    IEnumerator myEnumerator = myEnumerable.GetEnumerator();
    while (myEnumerator.MoveNext())
    {
        MessageBox.Show(myEnumerator.Current.ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

第一次写作虽然简单得多.

2. while和do..while

while (condition) {action}环路和do {action} while (condition)环路只是由第一个测试施加的动作,当第二个应用的动作,然后测试条件之前的状态的事实,从彼此不同.与其他do {..} while (..)循环相比,循环使用得非常少,因为即使最初未满足条件,它也至少运行一次动作(这可能导致麻烦,因为动作通常取决于条件).

while环比更普遍的forforeach的,它特别适用于对象的列表.该while环路只是有一个条件下去,它可以基于任何东西.例如:

string name = string.empty;
while (name == string.empty)
{
    Console.WriteLine("Enter your name");
    name = Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

要求用户输入他的名字,然后按Enter,直到他实际输入一些东西.正如您所看到的,与列表无关.

3.结论

当您浏览列表时,foreach除非您需要数字索引,否则应该使用,在这种情况下您应该使用for.当它与列表没有任何关系时,它只是一个程序结构,你应该使用while(..) {..}.

现在总结一些限制性较小的东西:.NET的第一个目标应该是使代码可读/可维护,使其按优先级顺序快速运行.任何达到这一点的东西对你都有好处.就个人而言,我认为foreach循环具有潜在的优势,它是最可读最快的.

编辑:还有一种情况是for循环很有用:当你需要索引以特殊方式浏览列表或者你需要在循环中修改列表时.例如,在这种情况下,因为我们要从myList中删除每个null元素:

for (int i=myList.Count-1; i>=0; i--)
{
    if (myList[i] == null) myList.RemoveAt(i);
}
Run Code Online (Sandbox Code Playgroud)

你需要for循环这里因为myList不能在foreach循环中修改,我们需要向后遍历它,因为如果你删除位置i的元素,所有索引> i的元素的位置都会改变.

但是自从LINQ以来,这些特殊结构的使用已经减少了.最后一个例子可以在LINQ中这样编写,例如:

myList.RemoveAll(obj => obj == null);
Run Code Online (Sandbox Code Playgroud)

LINQ是第二步,首先学习循环.