内容简介:开发中如果想要自己实现一个集合数据接口并且可以用
开发中如果想要自己实现一个集合数据接口并且可以用 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; } } 复制代码
控制台正常输出了添加的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
也有不少应用的地方例如遍历一个日期 读取文本文件的字符,读取一个内存流
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 用 go channel 实现素数迭代器、二叉查找树比较
- 少说话多写代码之Python学习051——类的成员(实现迭代器)
- 迭代器萃取与反向迭代器
- 浅谈python可迭代对象,迭代器
- 可迭代对象,迭代器(对象),生成器(对象)
- 终于把动态规划与策略迭代、值迭代讲清楚了
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。