class Program

{

static void Main(string[] args)

{

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

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

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

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

{

Console.WriteLine(array11[i]);

}

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

foreach (string s in array12)

{

Console.WriteLine(s);

}

/*结果

111

222

333

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

111

222

333

*/

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

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

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

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

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

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

{

Console.WriteLine(array21[i]);

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

}

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

foreach (string s in array22)

{

Console.WriteLine(s);

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

}

/*结果

111

BBB

CCC

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

111

222

333

*/

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

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

Console.ReadKey();

}

}

namespace for_foreach2

{

class Program

{

static void Main(string[] args)

{

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

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

E e = new E(array31);

foreach (string s in e)

{

Console.WriteLine(s);

}

/*result

333

222

111

Dispose here!

*/

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

Console.ReadKey();

}

}

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

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

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

public class E : System.Collections.IEnumerable

{

private InnerEnumerator inner;

public E(string[] array)

{

this.inner = new InnerEnumerator(array);

}

#region IEnumerable Members

public IEnumerator GetEnumerator()

{

return this.inner;

}

#endregion

private class InnerEnumerator : IEnumerator, IDisposable

{

private string[] s;

private int currentIndex;

public InnerEnumerator(string[] array)

{

this.s = array;

this.Reset();

}

#region IEnumerator Members

//Reset index to original(重置索引为原始的)

public void Reset()

{

this.currentIndex = s.Length - 1;

}

//Get Current object inner

public object Current

{

get

{

object o = this.s[this.currentIndex];

this.currentIndex--;

return o;

}

}

//Is there has any other object in the array?

public bool MoveNext()

{

if (this.currentIndex < 0)

{

return false;

}

return true;

}

#endregion

#region IDisposable Members

//Dispose Here()

public void Dispose()

{

Console.WriteLine("Dispose here!");

}

#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的日志 - 网易博客

黑马程序员-for和foreach的更多相关文章

  1. 黑马程序员——【Java高新技术】——代理

    ---------- android培训.java培训.期待与您交流! ---------- 一.“代理概述”及“AOP概念” (一)代理概述 1.问题:要为已存在的多个具有相同接口的目标类的各个方法 ...

  2. 黑马程序员+SQL基础(上)

    黑马程序员+SQL基础 ---------------<a href="http://edu.csdn.net"target="blank">ASP ...

  3. 黑马程序员+Winform基础(上)

    黑马程序员+Winform基础 ---------------<a href="http://edu.csdn.net"target="blank"> ...

  4. 黑马程序员—C语言的函数、数组、字符串

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.函数 定义:函数是代码复用的一种机制. 函数的基本语法: 返回类型 函数名 ( 参数类型 参 ...

  5. 黑马程序员:Java基础总结----泛型(高级)

    黑马程序员:Java基础总结 泛型(高级)   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 泛型(高级) 泛型是提供给javac编译器使用的,可以限定集合中的输入类型 ...

  6. 黑马程序员:Java基础总结----类加载器

    黑马程序员:Java基础总结 类加载器   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个 ...

  7. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  8. 黑马程序员:Java基础总结----枚举

    黑马程序员:Java基础总结 枚举   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 枚举 为什么要有枚举 问题:要定义星期几或性别的变量,该怎么定义?假设用1-7分别 ...

  9. 黑马程序员:Java基础总结----反射

    黑马程序员:Java基础总结 反射   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 反射 反射的基石:Class类 Class类代表Java类,它的各个实例对象又分别 ...

随机推荐

  1. 转:Github上最受关注的前端大牛,快来膜拜吧!

    原文来自于:http://code.csdn.net/news/2820990 本文列出了Github上最受关注的10位前端大牛.看看他们负责的项目和提交的代码,你是不是能从中学到些什么? 1. Pa ...

  2. [BZOJ 1801] [Ahoi2009]chess 中国象棋 【DP】

    题目链接:BZOJ - 1801 题目分析 对于50%的数据是可以直接状压 DP 的. 对于100%的数据,使用递推的 DP .(或者这只叫递推不叫 DP ?) 可以发现,每一行和每一列的棋子个数不能 ...

  3. 【Java】Java Socket编程(1)基本的术语和概念

    计算机程序能够相互联网,相互通讯,这使一切都成为可能,这也是当今互联网存在的基础.那么程序是如何通过网络相互通信的呢?这就是我记录这系列的笔记的原因.Java语言从一开始就是为了互联网而设计的,它为实 ...

  4. 【调侃】IOC前世今生(转)

    前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...

  5. 《深入Linux内核》 UNIX的一些故事

    Unix文件的类型1.普通文件2.目录3.符号链接4.面向块的设备文件5.面向字符的设备文件6.管道和命名管道7.套接字 点评:不明觉厉 打开文件进程只能访问“打开的”文件.为了打开一个文件,进程调用 ...

  6. Beauty Contest(graham求凸包算法)

    Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 25256   Accepted: 7756 Description Bess ...

  7. iOS应用架构浅谈

    (整理至http://www.cocoachina.com/ios/20150414/11557.html) 缘由 从事iOS工作一年多了,主要从事QQ钱包SDK开发和财付通app维护,随着对业务的慢 ...

  8. wp8模拟器中使用电脑键盘和模拟器的版本解释

    一:如图启用和关闭 二:电脑按键对应的手机的按键 三:模拟器的版本解释

  9. bzoj1588 [HNOI2002]营业额统计(Treap)

    1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 11485  Solved: 4062[Submit][Sta ...

  10. [Locked] Two Sum

    Two Sum II - Input array is sorted Given an array of integers that is already sorted in ascending or ...