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. hadoop输出统计

  2. Whitespace character

    In computer science, whitespace is any character or series of whitespace characters that represent h ...

  3. Ubiquitous Religions(并查集)

    Description There are so many different religions in the world today that it is difficult to keep tr ...

  4. Windows Server 2012 R2里十个极好的新功能

    Windows Server 2012 R2具备的众多新特点大大的增强了操作系统的功能性,同时也是在Windows Server 2012原有功能上的拓展.这里整理出Windows Server 20 ...

  5. 揭开Linux操作系统的Swap交换区之谜

    揭开Linux操作系统的Swap交换区之谜 Swap,即交换区,除了安装Linux的时候,有多少人关心过它呢?其实,Swap的调整对Linux服务器,特别是Web服务器的性能至关重要.通过调整Swap ...

  6. A Knight's Journey(dfs)

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25950   Accepted: 8853 Description Back ...

  7. 【Fiddler】手机抓包

    Fiddler (四) 实现手机的抓包 手机配置了后,Fiddler不开起来就什么也连接不了

  8. Linux系统下用户行为审计

    以下内容在RHEL 6.4下测试通过. 1.编写脚本Command_history.sh,生产历史命令记录文件,内容如下 #!/bin/bash [ -d /usr/lib/.cmdlog ] || ...

  9. 【动态规划】Vijos P1037 搭建双塔

    题目链接: https://vijos.org/p/1037 题目大意: 给n块砖的长度(n<=100),问从中任选m块砖能否建成2个相同高度的塔. 能的话求最高高度,不能输出 Impossib ...

  10. Solr多核的配置

    Solr 多核(MultiCore)配置 Solr Multicore意义 Solr Multicore 是 solr 1.3 的新特性.其目的一个solr实例,可以有多个搜索应用.< xmln ...