时间:2021-05-20
1.介绍
我们知道,我们要使一个类型支持foreach循环,就需要这个类型满足下面条件之一:
该类型实例如果实现了下列接口中的其中之一:
该类型中有公开的无参GetEnumerator()方法,且其返回值类型必须是类,结构或者接口,同时返回值类型具有公共 Current 属性和公共无参数且返回类型为 Boolean的MoveNext 方法。
上面的第一个条件,归根结底还是第二个条件的要求,因为这几个接口,里面要求实现的还是GetEnumerator方法,同时,接口中GetEnumerator的返回值类型IEnumerator接口中要实现的成员和第二条中返回值类型的成员相同。
C#9.0之前,是不支持采取扩展方法的方式给类型注入GetEnumerator方法,以支持foreach循环的。从C#9.0之后,这种情况得到了支持。
2. 应用与示例
在这里,我们定义一个People类,它可以枚举其所有组员Person,并且在其中定义了MoveNext方法和Current属性。同时,我们也通过扩展方法给People注入了GetEnumerator方法。这样,我们就可以使用foreach来枚举People对象了。
首先,我们来定义一个Person记录:
public record Person(string FirstName, string LastName);下来,我们来创建People类型,用来描述多个Person对象,并提供GetEnumerator返回值类型中所需的Current属性和MoveNext方法。在此,我们没有实现任何接口:
public class People:IDisposable//: IEnumerator<Person>{ int position = -1; private Person[] _people { get; init; } public People(Person[] people) { _people = people; } public bool MoveNext() { position++; return (position < _people.Length); } public Person Current { get { try { return _people[position]; } catch (IndexOutOfRangeException) { throw new InvalidOperationException(); } } } public void Reset() { position = -1; } public void Dispose() { Reset(); }}需要注意的是People中,由于没有通过使用前面的接口来实现支持foreach功能,这样就存在一个问题,就是第一次foreach循环完成后,状态还没有恢复到初始状态,第二次使用foreach进行枚举就没有可用项。因此我们添加了Reset方法用于手工恢复回初始状态,如果想让foreach能自动恢复状态,就让People实现接口IDisposable,并在其实现中,调用Reset方法。
然后,我们定义扩展方法,给People注入GetEnumerator方法
static class PeopleExtensions{ //public static IEnumerator<T> GetEnumerator<T>(this IEnumerator<T> people) => people; public static People GetEnumerator(this People people) => people;}最后,只要引用了扩展方法所在的命名空间,foreach循环就可以使用了。
var PersonList = new Person[3]{ new ("John", "Smith"), new ("Jim", "Johnson"), new ("Sue", "Rabon"),};var people = new People(PersonList);foreach (var person in people){ Console.WriteLine(person);}到这里,我们就完成了利用扩展方法来实现foreach循环的示例,为了方便拷贝测试,我们所有的代码放在一起就如下所示:
var PersonList = new Person[3]{ new ("John", "Smith"), new ("Jim", "Johnson"), new ("Sue", "Rabon"),};var people = new People(PersonList);foreach (var person in people){ Console.WriteLine(person);}public record Person(string FirstName, string LastName);public class People:IDisposable//: IEnumerator<Person>{ int position = -1; private Person[] _people { get; init; } public People(Person[] people) { _people = people; } public bool MoveNext() { position++; return (position < _people.Length); } public Person Current { get { try { return _people[position]; } catch (IndexOutOfRangeException) { throw new InvalidOperationException(); } } } public void Reset() { position = -1; } public void Dispose() { Reset(); }}static class PeopleExtensions{ //public static IEnumerator<T> GetEnumerator<T>(this IEnumerator<T> people) => people; public static People GetEnumerator(this People people) => people;}结束语
解除原有的限制,扩展方法GetEnumerator支持foreach循环,为特殊的需要提供了一种可能。
作者:MarkKang
出处:https:///markkang/
以上就是C# 9.0新特性——扩展方法GetEnumerator支持foreach循环的详细内容,更多关于C# 9.0新特性的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
For-Each循环For-Each循环也叫增强型的for循环,或者叫foreach循环。For-Each循环是JDK5.0的新特性(其他新特性比如泛型、自动装
for循环与foreach的区别foreach依赖IEnumerable.第一次varainGetList()时调用GetEnumerator返回第一个对象并赋
本文实例讲述了C#使用foreach循环遍历数组的方法。分享给大家供大家参考,具体如下:usingSystem;usingSystem.Collections.
C#语言提供的foreach语句是一个for语句循环的捷径,而且还促进了集合类的更为一致,先来看看它的定义格式:foreach语句的定义格式为:foreach(
本文实例讲述了C#使用foreach语句遍历二维数组的方法。分享给大家供大家参考。具体分析如下:如果通过for语句循环遍历二维数组需要两重循环才可以,二fore