c# 迭代器实现

栏目: ASP.NET · 发布时间: 5年前

内容简介:开发中如果想要自己实现一个集合数据接口并且可以用

开发中如果想要自己实现一个集合数据接口并且可以用 foreach 来遍历该集合,一般需要实现2个类

IEnumerable

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}
复制代码

IEnumerator

public interface IEnumerator
{
    bool MoveNext();
    void Reset();
    object Current { get; }
}
复制代码

GetEnumerator() 方法作用是需要得到一个IEnumerator接口的实例

MoveNext() 方法作用是判断这次是否可以遍历

Reset() 重置该迭代器的索引

Current 取出当前遍历的数据

接下来编写2个简单的类来实现foreach的遍历

public class MyList<TEntity> : IEnumerable<TEntity>
{
    private readonly int _initLength;
    private TEntity[] _list;
    
    public MyList()
    {
        _list = new TEntity[10];
        _initLength = 10;
    }
    
    public IEnumerator<TEntity> GetEnumerator()
    {
        return new MyEnumeratir(_list);
    }
    
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    
    public void Add(TEntity entity)
    {
        if(entity==null)
            throw new NullReferenceException("添加的entity 对象为Null");
        if (getNullLocation() == -1) ResetSize();
        int index = getNullLocation();
        _list[index] = entity;
    }
    
    private int getNullLocation()
    {
        for (int i = 0; i < _list.Length; i++)
        {
            if (_list[i] == null)
            {
                return i;
            }
        }
        return -1;
    }
    
    private void ResetSize()
    {
        TEntity[] newList = new TEntity[_list.Length+10];
        for (int i = 0; i < _list.Length; i++)
        {
             newList[i] = _list[i];
        }
        _list = newList;
    }
}

public class MyEnumerator<TEntity>:IEnumerator<TEntity>
{
    private TEntity[] _list;
    private int _index;
    private TEntity _current;
    
    public MyEnumerator(TEntity[] list)
    {
        _index = 1;
        _list = list;
    }
    
    public bool MoveNext()
    {
        _index++;
        if(_index==_list.Length) return false;
        TEntity obj = _list[_index];
        if(obj==null) return false;
        return true;
    }
    
    public void Reset()
    {
        _index= -1;
    }
    
    TEntity IEnumerator<TEntity>.Current
    {
        get
        {
            _current = _list[_index];
            return _current;
        }
    }
    
    public Object Current => _current;
}
复制代码

上面的编写的代码简单的实现了集合并且可以随意添加数据,接下来添加一下数据验证这个集合类是否可以正常遍历

class Program
{
    public static void Main(string[] args)
    {
        MyList<Student> myList = new MyList<Student>();
    }
    myList.Add(new Student
    {
        Name = "周杰伦",
        Age = 18,
        Sex = "男"
    });
    myList.Add(new Student
    {
        Name = "张靓颖",
        Age = 20,
        Sex = "女"
    });
    myList.Add(new Student
    {
        Name = "雅典啊",
        Age = 1000,
        Sex = "女"
    });
    foreach (var student in myList)
    {
        Console.WriteLine($"姓名:{student.Name} ----- 年龄:{student.Age} ----- 性别:{student.Sex}");
    }
    Console.ReadLine();
}
public class Student
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Sex { get; set; }
}
复制代码
c# 迭代器实现

控制台正常输出了添加的3条 Student 的实例对象

上面的代码中 MyEnumerator 编写了很长的代码还需要判断边条条件,如果要投入到实际生产环境当中还需要编写更多的边界条件判断很是麻烦。 不过C#开发团队提供了一个更加简单的语法糖来实现以上的操作那就是 关键字 yield

现在改写一下 MyList 中的方法 GetEnumerator()

public IEnumerator<TEntity> GetEnumerator()
{
    //return new MyEnumeratir(_list);
    for(int i=0;i<=_list.Length-1;i++)
    {
        if(_list[i]!=null)
        {
            yield return _list[i];
        }
    }
}
复制代码

这样看起来代码干净了不少哈 不过 yield 使用起来有几条限制

1.不能将 yield return 语句置于 try-catch 块中。 可将 yield return 语句置于 try-finally 语句的 try 块中。

2.可将 yield break 语句置于 try 块或 catch 块中,但不能将其置于 finally 块中。

3.如果 foreach 主体(在迭代器方法之外)引发异常,则将执行迭代器方法中的 finally 块。

上面的实例是解释了迭代器如何实现,实际开发中你这样写代码得让别人给骂死。

实际场景中 yield 也有不少应用的地方例如遍历一个日期 读取文本文件的字符,读取一个内存流


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

从零开始做运营

从零开始做运营

张亮 / 中信出版社 / 2015-11-1 / 49.00元

运营是什么?怎样做运营?产品和运营是什么关系?我是否适合从事互联网运营?为什么我做的运营活动收效甚微? 在互联网大热的今天,互联网运营成为一个越来越重要的岗位,事关网站、产品的发展与存亡。很多年轻人带着对互联网的热情投身到这个行业,却发现自己对这个行业所知甚少,对互联网运营更加陌生,甚至有一些有志于从事互联网运营的人,因为对运营缺乏了解而难以确定自己的职业发展方向。本书的出发点就在于此,它将......一起来看看 《从零开始做运营》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码