有关foreach的一些想法

在C#中,foreach的使用简化了很多循环语法的书写。如果我们仅仅把foreach当成for循环的省略写法的话,就显得有点大才小用了。

事实上,foreach与“迭代”和“枚举”密切相关。

C#编译器会把foreach语句转换为IEnumerable接口的方法和属性。

例如:

foreach (var p in persons)

{

Console.WriteLine(p);

}

以上代码迭代persons数组中的所有元素,并逐个显示他们。

foreach语句会解析成下面的代码。首先调用GetEnumerator()方法,获得数组的一个枚举。

在while循环中(只要MoveNext()返回true),用Current属性访问数组中的元素:

IEnumerator enumerator = persons.GetEnumerator();

while (enumerator.MoveNext())

{

Person p = (Person) enumerator.Current; Console.WriteLine(p);

}

这里要说明的是。用[]声明数组是C#中使用Array类的记号。Array类实现了IEnumerable接口中的GetEnumerator()方法。

所以使用foreach语句迭代数组,其实是使用了Array类中个GetEnumerator()方法。

也就是说,只要是实现了IEnumerable接口中的GetEnumerator()方法的类,都可以用foreach语句来迭代。

IEnumerable接口中的GetEnumerator()方法是这样定义的:

IEnumerator GetEnumerator()

其返回的类型是一个IEnumerator接口。

IEnumerator接口中的Current属性返回光标所在的元素。

IEnumerator接口中的MoveNext()方法移动到集合的下一个元素上,如果有这个元素,该方法就返回true。如果集合不再有更多的元素,该方法就返回false。

IEnumerator接口中的Reset()方法将光标重新定位于集合的开头。许多枚举会抛出NotSupportedException异常。

下面,我们来写一个实现了IEnumerable接口的类。

public class HelloCollection:IEnumerable

{

public IEnumerator GetEnumerator()

{

yield return "Hello";

yield return "World";

}

}

现在可以用foreach语句迭代了:

static void Main(string[] args)

{

HelloCollection
helloCollection=new HelloCollection ();

foreach (string s in
helloCollection )

{

Console.WriteLine(s);

}

}

实际上,yield return语句返回集合的一个元素,并移动到下一个元素上。它会将类HelloCollection解析成如下代码:

public class HelloCollection : IEnumerable

{

public IEnumerator GetEnumerator()

{

Enumertor enumerator = new Enumerator();

return enumerator;

}

public class Enumertor : IEnumerator, IDisposable

{

private int state;

private object current;

public Enumertor(int state)

{

this.state = state;

}

}

bool System.Collections .IEnumerator .MoveNext()

{

switch (state)

{

case 0:

current = "Hello";

state = 1;

return true;

case 1:

current = "World";

state = 2;

return true ;

case 2:

break ;

}

return false ;

}

void System.Collections .IEnumerator .Reset()

{

throw new NotSupportedException();

}

object System.Collections .IEnumerator .Current

{

get

{

return
current;

}

}

void IDisposable.Dispose()

{

}

}

foreach语句默认用GetEnumerator()方法迭代,也可以自行制定迭代方法。举例:

public class MusicTitles:IEnumerable

{

string[] names = { "Tubular Bells", "Hergest Ridge", "Ommadawn",
"Platinum" };

public IEnumerator GetEnumerator()  /*顺序迭代*/

{

for (int i = 0; i < 4; i++)

yield return names[i];

}

public IEnumerator Reverse()  /*逆序迭代*/

{

for (int i = 3; i >= 0; i--)

yield return names[i];

}

}

在foreach语句中不必写明使用GetEnumerator()方法迭代,因为这是默认方法。如下:

static void Main(string[] args)

{

MusicTitles titles = new MusicTitles();

foreach (string title in titles)

{

Console.WriteLine(title);

}

Console.WriteLine();

foreach (string title in titles.Reverse())

{

Console.WriteLine(title);

}

}

有关foreach的一些想法,布布扣,bubuko.com

时间: 2024-11-05 21:36:40

有关foreach的一些想法的相关文章

VS2015--win32工程配置的一些想法之在 Visual Studio 2015 中进行调试的同时分析性能

出处: https://msdn.microsoft.com/zh-cn/magazine/dn973013(en-us).aspx 许多开发商花了绝大多数时间获取应用程序才能正常发挥作用.更少的时间里专注于应用程序的性能.虽然有了很长一段时间分析工具在 Visual Studio 中的,他们是单独的一组学习工具.许多开发人员没有花时间去学习和使用它们的时候会出现性能问题. 这篇文章将介绍 Visual Studio 2015 年新的诊断工具调试器窗口. 它还将描述如何使用它来分析性能作为定期调

PHP--Warning: Invalid argument supplied for foreach() in ...

1.背景 今天学习PHPExcel的使用,在代码执行foreach($data as $value){...}的时候出现这样一个警告提示:Warning: Invalid argument supplied for foreach() in I:\WWW\PHPExcel\export.php on line 35:后来查询了一下,这个警告的意思是:foreach()遍历输出的是一无效的数组[注意,无效数组不等于空数组],而导致我这个错误的原因是,正确的代码应该是 [getType($i)这个方

C#缓存的一点想法及测试

项目开发中,用到了缓存,其中的一个列表项,可能要多线程处理,就有了下面的想法,具体的问题在代码中有详细说明,见下文. 1 static void Main(string[] args) { 2 3 4 5 测试缓存的想法(); 6 7 Console.WriteLine("测试结束!"); 8 Console.ReadKey(); 9 } 10 11 /// <summary> 12 /// 静态的缓存,测试缓存是否存放的指针 13 /// </summary>

探究foreach对于迭代变量的封装性的研究

众所周知教科书上对于foreach之中的注释是在遍历过程中无法改变其遍历的元素例如声明一个数组 int[] ii={0,1,2,3}; foreach(int m in ii){ m = 3;//错误 “m”是一个“foreach 迭代变量”,无法为它赋值 Console.WriteLine(m); } 由上面可以知道,我们无法改变数组里面的值,但是foreach语句是为了集合而创建的,数组只是集合的一种,而其他集合会是怎么样的呢?C#里面为我们创建好了好几个集合类,List<T> ,Arra

VS2015--win32project配置的一些想法之在 Visual Studio 2015 中进行调试的同一时候分析性能

出处: https://msdn.microsoft.com/zh-cn/magazine/dn973013(en-us).aspx 很多开发商花了绝大多数时间获取应用程序才干正常发挥作用.更少的时间里专注于应用程序的性能. 尽管有了非常长一段时间分析工具在 Visual Studio 中的,他们是单独的一组学习工具.很多开发者没有花时间去学习和使用它们的时候会出现性能问题. 这篇文章将介绍 Visual Studio 2015 年新的诊断工具调试器窗体. 它还将描写叙述怎样使用它来分析性能作为

Unity3D系列1 : foreach对于性能到底有没有影响

0x00 序言 本文无意比较for和foreach谁效率更高,不会设计到for和foreach取值之类的等等.单纯探讨foreach会不会影响unity3d效率. 事情开端是这样的,之前在看unity优化的时候,遇见了这么一句: 尽量不要使用foreach,而是使用for.foreach其实会涉及到迭代器的使用,而据传说每一次循环所产生的迭代器会带来24 Bytes的垃圾.那么循环10次就是240Bytes. 由于刚接触unity以及c#不久,当时没有仔细研究内在原理,只是简单相信了这个说法.于

foreach的一个&ldquo;奇怪&rdquo;现象&mdash;&mdash;实现原理分析

先看一个长长的代码,其实很简单,就是使用不同的方法迭代Map,对值进行修改,只要遇到foreach就发现赋值看似成功,实则失败. 就想搞清楚为什么,不想直接从搜索引擎搜来别人的总结好的背下来. 1.问题的引出 1.1.测试的源代码    1: public static void main(String[] args) {    2:     Map<String, String[]> map = new HashMap<String, String[]>();    3:    

15天学习MVC后的小结(分享经历与想法)

学习MVC已经有半个月,看了看日历,刚好半个月.分享了好几篇练习的博文:一,<创建第一个MVC应用程序> http://www.cnblogs.com/insus/p/3358560.html二,<@Styles的nameSpace是什么>http://www.cnblogs.com/insus/p/3358703.html三,<MVC应用程序使用Entity Framework>http://www.cnblogs.com/insus/p/3359111.html四,

C#并发实战Parallel.ForEach使用

前言:最近给客户开发一个伙食费计算系统,大概需要计算2000个人的伙食.需求是按照员工的预定报餐计划对消费记录进行检查,如有未报餐有刷卡或者有报餐没刷卡的要进行一定的金额扣减等一系列规则.一开始我的想法比较简单,直接用一个for循环搞定,统计结果倒是没问题,但是计算出来太慢了需要7,8分钟.这样系统服务是报超时错误的,让人觉得有点不太爽.由于时间也不多就就先提交给用户使用了,后面逻辑又增加了,计算时间变长,整个计算一遍居然要将近10分钟了.这个对用户来说是能接收的(原来自己手算需要好几天呢),但