C#中for和foreach的对比

最近在写代码的时候突然有个想法,写foreach的时候在想,用for代替foreach是不是除了写法差异以外完全没有什么影响?于是就很好奇,如果这两个函数效果完全一致,那为什么要保留for的写法?或者为什么会有foreach的写法出来?仅仅是为了写法简单一点吗?

带着好奇我大概测试了一些增删改的轮询情况

首先,创建一个整形数组待之后循环输出

int[] intArr = {1,2,3,4,5,6,7,8,9};

再创建一个整形List列表等待之后做输出

List<int> intList = new List<int>;
intList.Add(1);
intList.Add(2);
intList.Add(3);
intList.Add(4);
intList.Add(5);

for:使用数组:

for(var i=0 ; i<intArr.Count ; i++)
{
    if(intArr[i] == 1)
    {
        intArr[4] = 11; 
    }
    Console.WriteLine(intArr[i]);
}

输出:

1
2
3
4
11
6
7
8
9

foreach:使用数组:

foreach(int i in intArr)
{
    if(i == 1)
    {
        intArr[4] = 11;
    }
    Console.WriteLine(i);
}

输出:集合已修改;可能无法执行枚举操作。

小结:在for循环中修改数据会输出修改后的数据,而foreach循环中如果修改了正在循环的数据,那么将会返回错误。

for:使用List删除元素:

for(int i = 0; i < intList.Count ; i++)
{
    if(intList[i] == 1)
    {
        intList.Remove(3);
    }
    Console.WriteLine(intList[i]);
}

输出:

1
2
4
5

foreach:使用list删除元素:

foreach(int i in intList)
{
    if(i == 1)
    {
        intList.Remove(3)
    }
    Console.WriteLine(i);
}

输出:集合已修改;可能无法执行枚举操作。

新增元素同理

小结:for循环的过程中会每次去重新计算条件语句,而foreach循环则会因为条件语句被隐藏,且条件语句发生变化而返回错误。

这时我突然想起来之前经常用DataTable来做循环,同时给DataTable中的空值做赋值,所以对上面的结论产生了质疑,似乎事情并没有那么简单,于是我想重新用DataTable来测试一下。

当使用DataTable:

System.Data.DataTable DTInfo = new System.Data.DataTable();
DTInfo.Columns.Add("IntName", typeof(int));
System.Data.DataRow dr_info = DTInfo.NewRow();
dr_info["IntName"] = 10;
DTInfo.Rows.Add(dr_info);

foreach:使用DataTable修改:

foreach(System.Data.DataRow dr in DTInfo.Rows)
{
    if(Convert.ToInt32(dr["IntName"]) == 10)
    {
        dr["IntName"] = 11;
    }
    Console.WriteLine(dr["IntName"]);
}

输出:

11

foreach使用DataTable新增:

foreach(System.Data.DataRow dr in DTInfo.Rows)
{
    if(Convert.ToInt32(dr["IntName"]) == 10)
    {
        System.Data.DataRow dr_Add = DTInfo.NewRow();
        dr_Add["IntName"] = 10;
        DTInfo.Rows.Add(dr_Add);
    }
    Console.WriteLine(dr["IntName"]);
}

输出:集合已修改;枚举操作可能无法执行。

小结:在本次测试中,foreach很自然的反馈了DataTable内部数据的改变,但是当数据量发生变化的时候却提示了错误。数据量的变化问题暂且不说,数据本身发生变化却没有返回错误,这个结论与之前的结论显然冲突了。

此时我突然想到一种可能,想要验证就做了下面这个数组

List<String>[] myList = new List<String>[3];
myList[0] = new List<string>();
myList[1] = new List<string>();
myList[2] = new List<string>();
myList[0].Add("A");
myList[0].Add("B");
myList[0].Add("C");
myList[1].Add("a");
myList[1].Add("b");
myList[1].Add("c");
myList[2].Add("1");
myList[2].Add("2");
myList[2].Add("3");

接着用foreach循环输出并试图修改其中的一个值

foreach (List<string> ls in myList)
{
    if (ls[0] == "A")
    {
        myList[2][0] = "4";
    }
    Console.WriteLine("ls[0]");
}

输出:

A
a
4

至此,大概的原因应该是找到了。

结论:在C#中,数据类型大概有两种,一种是值类型,一种是引用类型。值类型的变量直接在线程栈中分配空间,而引用类型的变量会在托管堆中分配空间,在线程栈中只有一个指向托管堆位置的空箱。在这两种基本类型的基础上有一种类型叫复合类型,它是说多个值类型的复合(值复合类型)或多个引用类型的复合(引用复合类型)。

特例:下面是我再测试的过程中试出来的一些其他情况

若在foreach操作数组时将intArr转为List:

foreach(int i in intArr.ToList())
{
    if(i == 1)
    {
        intArr[4] = 11;
    }
    Console.WriteLine(i);
}

输出:

1
2
3
4
5
6
7
8
9

若在for删除List元素时,删除已经循环过的元素:

for(int i = 0; i < intList.Count ; i++)
{
    if(intList[i] == 4)
    {
        intList.Remove(3);
    }
    Console.WriteLine(intList[i]);
}

输出:

1
2
3
5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值