c#中IEnumerable简单实现及 yield return 语法糖

c#中IEnumerable简介及简单实现

IEnumerable这个接口在MSDN上是这么说的,它是一个公开枚举数,该枚举数支持在非泛型集合上进行简单的迭代。换句话说,对于所有数组的遍历,都来自IEnumerable,那么我们就可以利用这个特性,来定义一个能够遍历字符串的通用方法.

下面先贴出code.

 代码如下 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace mycs
{
    class Program
    {
        static void Main(string[] args)
        {
            charlist mycharlist = new charlist("hello world");
            foreach (var c in mycharlist)
            {
                Console.Write(c);
            }
          Console.ReadLine();
        }
    }

    class charlist : IEnumerable
    {
        public string TargetStr { get; set; }

        public charlist(string str)
        {
            this.TargetStr = str;
        }
        public IEnumerator GetEnumerator()
        {
            //c# 1.0
            return new CharIterator(this.TargetStr);
            //c# 2.0
            /*
            for (int index = this.TargetStr.Length; index > 0;index-- )
            {
                yield return this.TargetStr[index - 1];
            }
              */
        }
    }
    class CharIterator : IEnumerator
    {
        public string TargetStr { get; set; }
        public int position { get; set; }

        public CharIterator(string targetStr)
        {
            this.TargetStr = targetStr;
            this.position = this.TargetStr.Length;
        }
        public object Current
        {
            get
            {
                if (this.position==-1||this.position==this.TargetStr.Length)
                {
                    throw new InvalidOperationException();
                }
                return this.TargetStr[this.position];
            }
        }
        public bool MoveNext()
        {
            if (this.position!=-1)
            {
                this.position--;
            }
            return this.position > -1;
        }
        public void Reset()
        {
            this.position = this.TargetStr.Length;
        }
    }
}

在上面的例子c# 1.0中,CharIterator就是迭代器的实现,position字段存储当前的迭代位置,通过Current属性可以得到当前迭代位置的元素,MoveNext方法用于更新迭代位置,并且查看下一个迭代位置是不是有效的。

当我们通过VS单步调试下面语句的时候

foreach (var c in charList)
代码首先执行到foreach语句的charList处获得迭代器CharIterator的实例,然后代码执行到in会调用迭代器的MoveNext方法,最后变量c会得到迭代器Current属性的值;前面的步骤结束后,会开始一轮新的循环,调用MoveNext方法,获取Current属性的值。

通过C# 1.0中迭代器的代码看到,要实现一个迭代器就要实现IEnumerator接口,然后实现IEnumerator接口中的MoveNext、Reset方法和Current属性。

在C# 2.0中可以直接使用yield语句来简化迭代器的实现。

如上面public IEnumerator GetEnumerator()方法中注释掉的部分.

通过上面的代码可以看到,通过使用yield return语句,我们可以替换掉整个CharIterator类。

yield return语句就是告诉编译器,要实现一个迭代器块。如果GetEnumerator方法的返回类型是非泛型接口,那么迭代器块的生成类型(yield type)是object,否则就是泛型接口的类型参数。


C#中yield return 语法糖

 public IEnumerator GetEnumerator()
        {
            for (int index = this.TargetStr.Length; index > 0;index-- )
            {
                yield return this.TargetStr[index - 1];
            }
              */
        }

迭代器yield return的语法就是告诉编译器.这个方法不是一个简单的方法.而是实现了一个迭代器块的方法.这个方法被声明为返回IEnumerator的一个接口.所以就只能使用迭代器来实现返回类型为IEnumerable,IEnumerator或泛型等价物的方法.如果方法声明的返回类型是非泛型接口,那么迭代器的生成类型是object,否则就是泛型接口的参数类型.例如,如果方法声明为返回值为IEnumerator,那么就会得到string类型的生成类型.

来看看下面的这段代码

public static IEnumerable
ReadLines(string filename)
        {
            using (TextReader reader = File.OpenText(filename))
            {
                string line;
                while ((line=reader.ReadLine()) != null)
                {
                    yield return line;
                }
            }
        }

可以看到,上面这段代码实现了对于一个文件的遍历读取每一行.

在foreach中释放迭代器非常重要.它可以确保阅读器被清理干净.迭代器方法中的using语句扮演了try/finally块.在达到文件末尾或者中途调用IEnumerable的Dispose方法,将进入finally块来释放迭代器.

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索string
, 接口
, 代码
, this
, 类型
yield
c站、c语言、cf、ch、c罗,以便于您获取更多的相关知识。

时间: 2024-11-16 07:44:58

c#中IEnumerable简单实现及 yield return 语法糖的相关文章

C#的yield return返回不可序列化的IEnumerable和IEnumerator

C#的yield return返回不可序列化的IEnumerable和IEnumerator .NET中的大多数常见IEnumerable和IEnumerator都是可以序列化的(有Serializable特性).比如Array,Dictionary<K,V>, HashSet<T>, List<T>, LinkedList, Queue<T>, Stack<T>, String, ResourceSet--等等类.而且一般可序列化的IEnume

C#中yield return用法

转载:http://www.jb51.net/article/54810.htm         http://www.cnblogs.com/HunterWei/archive/2012/06/13/csharpyieldreturn.html         http://www.cnblogs.com/nankezhishi/archive/2009/03/20/1418086.html         http://kb.cnblogs.com/page/42580/ 简单地说,当希望获

托管C++调用DLL中的方法时遇到yield时该如何? [问题点数:40分]

问题描述 假设className,methodName是参数被传入我用下面的代码调用了某个DLL中的方法Assembly^dllAssembly=Assembly::LoadFrom(dllPath);array<System::Type^>^selectType=dllAssembly->GetTypes(className);MethodInfo^selectedMethod=selectType->GetMethod(methodName);System::Object^in

Python的Flask框架中实现简单的登录功能的教程

  Python的Flask框架中实现简单的登录功能的教程,登录是各个web框架中的基础功能,需要的朋友可以参考下 回顾 在前面的系列章节中,我们创建了一个数据库并且学着用用户和邮件来填充,但是到现在我们还没能够植入到我们的程序中. 两章之前,我们已经看到怎么去创建网络表单并且留下了一个实现完全的登陆表单. 在这篇文章中,我们将基于我门所学的网络表单和数据库来构建并实现我们自己的用户登录系统.教程的最后我们小程序会实现新用户注册,登陆和退出的功能. 为了能跟上这章节,你需要前一章节最后部分,我们

VB.NET中的简单Web Service例程

web VB.NET中的简单Web Service例程 本文和附带的源码向您演示了在.NET开发环境下创建一个WEB服务是如何得简单,同时演示了客户端如何使用这个WEB服务.例程创建了一个计算器的简单WEB服务,它有三个方法:加.减和除. 下载文件包WebService_mehta.zip包含所有演示文件: Calculator.asmx HTMLClient.Html InetClient (VB6 Project) Calculator.asmx代码 <%@ WebService Langu

在Python的Tornado框架中实现简单的在线代理的教程

  这篇文章主要介绍了在Python的Tornado框架中实现简单的在线代理的教程,代理功能是一个常见的网络编程实现,需要的朋友可以参考下 实现代理的方式很多种,流行的web服务器也大都有代理的功能,比如http://www.tornadoweb.cn用的就是nginx的代理功能做的tornadoweb官网的镜像. 最近,我在开发一个移动运用(以下简称APP)的后台程序(Server),该运用需要调用到另一平台产品(Platform)的API.对于这个系统来说,可选的一种实现方式方式是APP同时

实例讲解PHP设计模式编程中的简单工厂模式_php实例

简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式.简单工厂模式是由一个工厂对象决定创建出那一种产品类的实例. 1.工厂模式的几种形态工厂模式专门负责将大量有共同接口的类实例化.工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类.工厂模式有以下几种形态: (1)简单工厂(Simple Factory)模式,又称静态工厂方法模式(Static Factory Method Pattern). (2)工厂方法(Factory Meth

VS2005/AJAX-VS2005中AJAX简单应用

VS2005/AJAX-VS2005中AJAX简单应用 AJAX不用说大家都明白,不明白的请百度或Google一下人家比我说的专业,笔者写此篇文章不在于介绍多深奥的东西,这样只举一个很简单的例子来引导到大家.此例只为让大家明白AJAX的基本的调用需要做那些事情笔者用的是VS2005引用AJAX2.0程序集(AJAXPro.2.dll) . 在web.config文件中的<system.web>加入以下设置 <httpHandlers> <add verb="POST

Zend Framework中的简单工厂模式 图文_php技巧

前段时间用来ZF,把他当黑盒感觉不是很好,一直有看其源码的冲动,但是...如果一点一点点看的话,挑战确实有些大了.某天又然后想到好久没复习设计模式了.综合一下,复习一个设计模式之后在ZF中找一下使用这模式的源码吧,不读所有源码,读读比较"高级"的部分吧,要说模式,暂时不知道是不是所有模式ZF里面都有,但是应该有足够的模式够我最近看了,在说可以找找其他开源的软件来找模式.这段时间被各种笔试神马乱七八糟的把生活搞得稍微有点乱,但是不管怎样,复习还是必须的吧.再说一下ZF吧,ZF一个好处就是