首页 > 学院 > 开发设计 > 正文

黑马程序员-for和foreach

2019-11-17 01:29:21
字体:
来源:转载
供稿:网友

黑马程序员-for和foreach

classPRogram

{

staticvoidMain(string[]args)

{

Console.WriteLine("***第一种情况************************************************");

string[]array11=newstring[]{"111","222","333"};

string[]array12=newstring[]{"111","222","333"};

for(inti=0;i<array11.Length;i++)

{

Console.WriteLine(array11[i]);

}

Console.WriteLine("=========================");

foreach(stringsinarray12)

{

Console.WriteLine(s);

}

/*结果

111

222

333

=========================

111

222

333

*/

//都是根据length来对数据进行循环

//不同的是foreach里自动对array进行index+1的操作来循环,而for则是自己的代码控制的

Console.WriteLine("***第二种情况************************************************");

string[]array21=newstring[]{"111","222","333"};

string[]array22=newstring[]{"111","222","333"};

for(inti=0;i<array21.Length;i++)

{

Console.WriteLine(array21[i]);

array21=newstring[]{"AAA","BBB","CCC"};

}

Console.WriteLine("=========================");

foreach(stringsinarray22)

{

Console.WriteLine(s);

array22=newstring[]{"AAA","BBB","CCC"};

}

/*结果

111

BBB

CCC

=========================

111

222

333

*/

//不一样了吧,看来在foreach内部的循环中对源数据的更改不是即时生效的

//在foreach(...)循环里尽量不要更改操作的源数据

Console.ReadKey();

}

}

namespacefor_foreach2

{

classProgram

{

staticvoidMain(string[]args)

{

//使用测试类E,做for和foreach的循环

string[]array31=newstring[]{"111","222","333"};

Ee=newE(array31);

foreach(stringsine)

{

Console.WriteLine(s);

}

/*result

333

222

111

Disposehere!

*/

//差异出现了,这次是按照倒序的方式,而且还自动调用了Dispose方法!

Console.ReadKey();

}

}

//根据MS的参考,能在foreach上做循环的只能是实现了IEnumerable接口。

//(事实上,System.Array也是实现了IEnumerable接口的)

//这儿做一个在IEnumerable上的循环

publicclassE:System.Collections.IEnumerable

{

privateInnerEnumeratorinner;

publicE(string[]array)

{

this.inner=newInnerEnumerator(array);

}

#regionIEnumerableMembers

publicIEnumeratorGetEnumerator()

{

returnthis.inner;

}

#endregion

privateclassInnerEnumerator:IEnumerator,IDisposable

{

privatestring[]s;

privateintcurrentIndex;

publicInnerEnumerator(string[]array)

{

this.s=array;

this.Reset();

}

#regionIEnumeratorMembers

//Resetindextooriginal(重置索引为原始的)

publicvoidReset()

{

this.currentIndex=s.Length-1;

}

//GetCurrentobjectinner

publicobjectCurrent

{

get

{

objecto=this.s[this.currentIndex];

this.currentIndex--;

returno;

}

}

//Istherehasanyotherobjectinthearray?

publicboolMoveNext()

{

if(this.currentIndex<0)

{

returnfalse;

}

returntrue;

}

#endregion

#regionIDisposableMembers

//DisposeHere()

publicvoidDispose()

{

Console.WriteLine("Disposehere!");

}

#endregion

}

}

}

综合上面,得出如下结论:1.for循环并不依赖于数组或其他形式的组式数据结构,只是简单的 在调用了代码后,进行一个判断,判断是否要继续。 (非常类似于do..while和while循环--在这里不作具体分析了^_^~~)2.foreach循环如果作用在一个基于System.Array的类型之上的数组的话,编译器会自动优化成与for循环非常类似 的代码,只是调用的指命有细微的差别,并且检查(包括编译阶段和运行时)会比for严格的多3.foreach循环作用在一个非System.Array类型上(且一定要是实现了IEnumerable接口的类),会先调用 IEnumerable.GetEnumerator()方法获取一个Enumertor实例,再在获取的Enumertor实例上调用 GetCurrent()和MoveNext()方法,最后判断如果Enumertor实例如果实现了IDispose接口,就自动调用 IDispose.Dispose()方法!

那么我们应该分别在那些地方用for和foreach捏建议:1.在有对所循环的本体(System.Array)做赋值操作时,尽量不要用Foreach()。2.foreach比for更灵活。(可在MoveNext()和GetCurrent()里编写自己的代码). 自己编写的类如果实现了IEnumerable接口的话,就可以用foreach循环了,而不管内部是否有一个真实的数组, 并且可以自定义循环的规则。3.从OO的原则看,foreach循环更适于多数情况的使用 (事实上,foreach的实现是典型的Iterator模式,下面有简单的描述它的好处) 想用统一的调用循环接口时,foreach是最佳的选择 (MS有很多类就是这样的,例如前面提到的DataRowCollection.)

参考至:C#里for和foreach的区别 - lyh830612的日志 - 网易博客


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表