写代码必不可少会用到循环,常用的无非就是for、switch、while等,这三个使用的时候可能会比较清楚的知道该用哪个比较合适。但是for循环这家伙有个近亲,foreach,也是有着遍历的作用,那到底怎么区分for和foreach的,什么情况下用哪一个更合适呢?那今天就来总结一下
先来看一下两者的表现形式吧
for(表达式1;循环条件;表达式2)
{
循环体
}
foreach(数据类型 变量 in 数组或集合)
{
循环体
}
For循环是一种迭代循环,是我们在已知循环次数的情况下重复执行的代码。其中,初始化表达式用于初始化循环变量;循环条件表达式用于判断是否继续执行循环;循环迭代表达式用于更新循环变量的值。循环体是需要重复执行的代码块。
For循环的执行过程是:首先执行初始化表达式,然后判断循环条件表达式的值,如果为true,则执行循环体,并执行循环迭代表达式。重复执行这个过程,直到循环条件表达式为false,循环结束。
Foreach循环f用于遍历数组、集合或其他实现了IEnumerable接口的数据源中的元素,其中,数据类型是要遍历的数组或集合中元素的类型,变量是每次循环时接收数组或集合中的元素的变量名,数组或集合是要遍历的数据源,循环体是需要执行的代码块。
Foreach循环会自动遍历数据源中的每个元素,并将当前元素赋值给变量,然后执行循环体中的代码。循环会一直执行,直到遍历完所有的元素。
使用foreach有两个优点
默认调用Dispose方法
语法更简单
但是for循环与之相比有一个巨大的优点,for循环可以用于任何形式的循环性工作。此外,foreach是不支持循环时对集合进行增删操作。比如,运行下面代码会抛出异常InvalidOperationException:
List<int> list=new List<int>(){0,1,2,3};
foreach (int item in list)
{
list.Remove(item);
Console.WriteLine(item);
}
这样写才是正确的
for (int i = 0; i < list.Count; i++)
{
list.Remove(list[i]);
Console.WriteLine(list[i]);
}
什么原因导致的呢?
foreach循环使用了迭代器进行集合的遍历,它在FCL提供的跌代替内部维护了一个对集合版本的控制。
那么什么是集合版本?简单来说,其实它就是一个整形的变量,任何对集合的增删操作都会使版本号加1.foreach会调用MoveNext方法来遍历元素,在MoveNext方法内部会进行版本号的检测,一旦检测到版本号有变动,就会抛出InvalidOperationException异常。
如果使用for循环就不会带来这样的问题。for直接使用索引器,它不对集合版本号进行判断,所以不会存在以为集合的变动而带来的异常(当然,超出索引长度这种异常情况除外)。
无论是for循环还是foreach循环,内部都是对该数组的访问,而迭代器仅仅是多进行了一次版本检测。
for循环适用于已知循环次数、需要通过索引访问元素或需要灵活控制循环条件的情况。而foreach循环适用于遍历数组或集合等数据源、不需要索引访问元素的情况。根据具体的需求和场景,选择合适的循环结构可以提高代码的可读性和效率。