c# 迭代器实现

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

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

开发中如果想要自己实现一个集合数据接口并且可以用 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 也有不少应用的地方例如遍历一个日期 读取文本文件的字符,读取一个内存流


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

查看所有标签

猜你喜欢:

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

Head First Python

Head First Python

Paul Barry / O'Reilly Media / 2010-11-30 / USD 49.99

Are you keen to add Python to your programming skills? Learn quickly and have some fun at the same time with Head First Python. This book takes you beyond typical how-to manuals with engaging images, ......一起来看看 《Head First Python》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具