枚举

在foreach语句中使用枚举,可以迭代集合中的元素,且无需知道集合中的元素个数.

数组或集合实现带GetEumerator()方法的IEumerable接口.GetEumerator()方法返回一个实现IEunmerable接口的枚举.

GetEnumerator()方法用IEnumerable接口定义.foreach语句并不真的需要在集合类中实现这个借口.有一个名为GetEnumerator()的方法,他返回实现了IEnumerator接口的对象就足够了.

IEnumerator接口

foreach语句使用IEnumerator接口的方法和属性,迭代集合中的所有元素.为此IEnumerator定义了Current属性,来返回光标所在的元素,该接口的MoveNext()方法移动到集合的下一个元素上,如果有这个元素,该方法就返回true.如果集合不再有更多的元素,该方法就返回false.

这个借口的泛型版本IEnumerator<T>派生自接口IDisposable,因此定义了Dispose()方法,来清理枚举器占用的资源.

foreach语句

C#的foreach语句不会解释为IL代码中的foreach语句.C#编译器会把foreach语句转换为IEnumerable接口的方法和属性.案例:

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

foreach (var item in arr)

{

Console.WriteLine(item);

}

很明显,foreach语句很简洁,但是他的有点不仅仅在于此,它的效率也是很高的,不用考虑数组是几维的.案例:

int[,] array = new int[8, 8];

for (int i = 0; i < array.GetLength(0); i++)

{

for (int j = 0; j < array.GetLength(1); j++)

{

Console.WriteLine(array[i,j].ToString());

}

}

Console.ReadKey();

使用foreach:

foreach (int item in array)

{

Console.WriteLine(item.ToString());

}

对于三维或者更多维,foreach语句不用发生任何变化,而对于for语句就要进行修改了.

foreach完成类型转换操作,案例:

int[] array = new int[100];

ArrayList aList = new ArrayList();

aList.AddRange(array);

foreach (int item in aList)

{

Console.WriteLine(item.ToString());

}

for (int i = 0; i < aList.Count; i++)

{

int n = (int)aList[i];

Console.WriteLine(n.ToString());

}

Console.ReadKey();

foreach并没有增加资源使用,由于对于继承了IEnumerable接口的数据类型,才能使用foreach语句,那么对于使用foreach会访问IEnumerable接口中的GetEnumerator()方法来进行枚举,那么对应如上的foreach语句,对应的语句如下:

IEnumerator it = aList.GetEnumerator() as IEnumerator;

using (IDisposable disp = it as IDisposable)

{

while (it.MoveNext())

{

int elem = (int)it.Current;

Console.WriteLine(elem.ToString());

}

}

也即是说再出了foreach语句之后对于IEnumerator的对象也进行IDispose处理.

foreach的两种限制

不能修改枚举成员:

int[] array = new int[100];

foreach (var item in array)

{

item++;//这是错误的,因为枚举成员是只读的

Console.WriteLine(item.ToString());

}

不要对集合进项删除操作:

int[] array = new int[100];

ArrayList alist = new ArrayList();

alist.AddRange(array);

foreach (var item in alist)

{

alist.Remove(item);//这是错误的

Console.WriteLine(item.ToString());

}

对于删除成员和修改成员可以使用for循环来处理,对于一个记录集的多条数据删除问题,也是经常出现的问题,由于在一些记录集中进行删除的时候,在删除操作之后相应的索引也发生了变化,这时候的删除要反过来进行删除:

int[] array = new int[100];

ArrayList alist = new ArrayList();

alist.AddRange(array);

for (int i = alist.Count-1; i >=0; i--)

{

int n = (int)alist[i];

if (n==5)

{

alist.RemoveAt(i);

}

Console.WriteLine(n.ToString());

}

除了上述提到的foreach的两个约束外,foreach可以用于人和循环.

yield语句

C#中的yield语句便于创建枚举器.

yield语句的两种形式:

1.yield return <expression>

2.yield break;

使用一个yield return语句返回集合的一个元素

包含yield语句的方法或属性是迭代器.迭代器必须满足下列要求:

a.返回类型必须是IEnumerable,IEnumerable<T>,IEnumerator或IEnumerator<T>

b.他不能有任何ref或out参数.

yield return语句不能位于try-catch块;yield return语句可以位于try-finally的try中

yield return语句返回集合的一个元素,并移动到下一个元素上.yield break可以停止迭代.

class Program

{

static void Main(string[] args)

{

HelloCollection hello = new HelloCollection();

foreach(string item in hello)

{

Console.WriteLine(item);

}

Console.ReadKey();

}

}

public class HelloCollection

{

public  IEnumerator<string> GetEnumerator()

{

//yield return语句返回集合的一个元素,并移动到下一个元素上

//yield break可以终止迭代

yield return "hello";

yield return "world";

}

}

使用yield return语句实现以不同方式迭代集合的类:

using System;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace 枚举

{

class Program

{

static void Main(string[] args)

{

MusicTitles music = new MusicTitles();

foreach(var item in music.GetEnumerator())

{

Console.WriteLine(item);

}

Console.WriteLine();

foreach (string item in music.Reverse())

{

Console.WriteLine(item);

}

Console.WriteLine();

foreach (var item in music.Subset(2,2))

{

Console.WriteLine(item);

}

Console.ReadKey();

}

}

public class MusicTitles

{

string[] names = {"a","b","c","d" };

public IEnumerable<string> GetEnumerator()

{

foreach (string item in names)

{

yield return item;

}

}

public IEnumerable<string> Reverse()

{

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

{

yield return names[i];

}

}

public IEnumerable<string> Subset(int index, int offert)

{

for (int i = index; i < index+offert; i++)

{

yield return names[i];

}

}

}

}

C#编程(三十五)----------foreach和yield的更多相关文章

  1. centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件、目录属性 shell数组简单用法 $( ) 和${ } 和$(( )) 与 sh -n sh -x sh -v 第三十五节课

    centos   shell脚本编程1 正则  shell脚本结构  read命令  date命令的用法  shell中的逻辑判断  if 判断文件.目录属性  shell数组简单用法 $( ) 和$ ...

  2. NeHe OpenGL教程 第三十五课:播放AVI

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  3. JAVA之旅(三十五)——完结篇,终于把JAVA写完了,真感概呐!

    JAVA之旅(三十五)--完结篇,终于把JAVA写完了,真感概呐! 这篇博文只是用来水经验的,写这个系列是因为我自己的java本身也不是特别好,所以重温了一下,但是手比较痒于是就写出了这三十多篇博客了 ...

  4. 第三百三十五节,web爬虫讲解2—Scrapy框架爬虫—豆瓣登录与利用打码接口实现自动识别验证码

    第三百三十五节,web爬虫讲解2—Scrapy框架爬虫—豆瓣登录与利用打码接口实现自动识别验证码 打码接口文件 # -*- coding: cp936 -*- import sys import os ...

  5. 孤荷凌寒自学python第三十五天python的文件操作之针对文件操作的os模块的相关内容

     孤荷凌寒自学python第三十五天python的文件操作之针对文件操作的os模块的相关内容 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.打开文件后,要务必记得关闭,所以一般的写法应当 ...

  6. 剑指Offer(三十五):数组中的逆序对

    剑指Offer(三十五):数组中的逆序对 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/bai ...

  7. Java进阶(三十五)java int与integer的区别

    Java进阶(三十五)java int与Integer的区别 前言 int与Integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而Integer是对象 ...

  8. Gradle 1.12用户指南翻译——第三十五章. Sonar 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  9. SQL注入之Sqli-labs系列第三十四关(基于宽字符逃逸POST注入)和三十五关

    开始挑战第三十四关和第三十五关(Bypass add addslashes) 0x1查看源码 本关是post型的注入漏洞,同样的也是将post过来的内容进行了 ' \ 的处理. if(isset($_ ...

  10. “全栈2019”Java多线程第三十五章:如何获取线程被等待的时间?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

随机推荐

  1. Linux umount的device is busy问题

    现象: [root@dbserver ~]# df -h文件系统 容量 已用 可用 已用%% 挂载点/dev/vda1 9.9G 3.9G 5.6G 41% /tmpfs 3.9G 100K 3.9G ...

  2. PHPWeb开发相关知识

    转载:https://blog.csdn.net/wj610671226/article/details/78426698 正则表达式 作用:分割.查找.匹配.替换字符串 分割符:正斜线(/).has ...

  3. Latex常用整理

    会不断更新添加,以便写论文的时候快速查找. 项目 带编号 \begin{enumerate} \setlength{\itemsep}{0pt} \setlength{\parsep}{0pt} \s ...

  4. linux通过wget直接下载jdk

    下载语句: tar包下载 wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-se ...

  5. 【LOJ】#2511. 「BJOI2018」双人猜数游戏

    题解 设\(f[p][a][b]\)表示询问了\(p\)次,答案是\(a,b\)是否会被猜出来 然后判断如果\(p = 1\) 第一个问的\(Alice\),那么\([s,\sqrt{nm}]\)约数 ...

  6. Java基础常见英语词汇(共70个)

    ——————————ASP.Net+Android+IOS开发..Net培训.期待与您交流!—————————— Java英文单词 OO: object—oriented ,面向对象 OOP:obje ...

  7. 利用 gdb 探究main(int argc, char *argv[]){} 中的char *argv[]

    在 Linux 系统中编写小程序 代码如下 编译并采用gdb调试  在调试之前设置三个参数   a   bb   ccc 输入 start 执行代码到 return 0; 从这里可以看到 argc = ...

  8. vue-awesome-swiper使用纪实

    最近做一个项目,需要用到轮播和全屏滑动功能,所以用到了vue-awesome-swiper插件,以下为个人记录下此插件的用法. 效果说明: 上面部分是个轮播图,自动开始轮播,轮播间隔为3000ms 推 ...

  9. 整理低版本ie兼容问题的解决方案

    CSS hack \9    所有的IE10及之前 *     IE7以及IE7以下版本的 _     IE6以及IE6以下版本的      !important  提升样式优先级权重 1.ie6,7 ...

  10. android 的安全问题

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 1,webView的js脚本引发的安全 2,代码的混淆加密.还可采用第三方apk加固程序 ...