服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# 9.0新特性——扩展方法GetEnumerator支持foreach循环

C# 9.0新特性——扩展方法GetEnumerator支持foreach循环

2022-10-18 11:40markkang C#

这篇文章主要介绍了C# 9.0新特性——扩展方法GetEnumerator支持foreach循环的相关资料,帮助大家更好的理解和学习c# 9.0,感兴趣的朋友可以了解下

1.介绍

我们知道,我们要使一个类型支持foreach循环,就需要这个类型满足下面条件之一:

该类型实例如果实现了下列接口中的其中之一:

  • System.Collections.IEnumerable
  • System.Collections.Generic.IEnumerable<T>
  • System.Collections.Generic.IAsyncEnumerable<T>

该类型中有公开的无参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记录:

?
1
public record Person(string FirstName, string LastName);

下来,我们来创建People类型,用来描述多个Person对象,并提供GetEnumerator返回值类型中所需的Current属性和MoveNext方法。在此,我们没有实现任何接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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方法

?
1
2
3
4
5
static class PeopleExtensions
{
  //public static IEnumerator<T> GetEnumerator<T>(this IEnumerator<T> people) => people;
  public static People GetEnumerator(this People people) => people;
}

最后,只要引用了扩展方法所在的命名空间,foreach循环就可以使用了。

?
1
2
3
4
5
6
7
8
9
10
11
12
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循环的示例,为了方便拷贝测试,我们所有的代码放在一起就如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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://www.cnblogs.com/markkang/

以上就是C# 9.0新特性——扩展方法GetEnumerator支持foreach循环的详细内容,更多关于C# 9.0新特性的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/markkang/p/14018990.html

延伸 · 阅读

精彩推荐
  • C#Unity3D游戏开发数据持久化PlayerPrefs的用法详解

    Unity3D游戏开发数据持久化PlayerPrefs的用法详解

    在本篇文章里小编给大家整理了关于Unity3D游戏开发之数据持久化PlayerPrefs的使用的相关知识点内容,需要的朋友们参考下。...

    laozhang4222022-08-03
  • C#C#实现输入法功能详解

    C#实现输入法功能详解

    本文主要介绍了C#实现输入法的相关知识。具有很好的参考价值。下面跟着小编一起来看下吧...

    YSWALLE10382021-12-29
  • C#不用IDE写C#的Hello World的方法

    不用IDE写C#的Hello World的方法

    这篇文章主要介绍了不用IDE写C#的Hello World的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    C#教程网10482021-11-01
  • C#C#中标准的IDispose模式代码详解

    C#中标准的IDispose模式代码详解

    在本篇文章中小编给大家分享的是关于C#中标准的IDispose模式的实例用法相关内容,有需要的朋友们测试下。...

    Leo_wlCnBlogs9162022-08-05
  • C#Unity实现注册登录模块

    Unity实现注册登录模块

    这篇文章主要为大家详细介绍了Unity实现注册登录模块,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    DwarfTitan9292022-08-28
  • C#C#自定义音乐播放器进度条

    C#自定义音乐播放器进度条

    这篇文章主要为大家详细介绍了C#自定义音乐播放器进度条效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    波谷10692022-01-17
  • C#C#导出数据到excel如何提升性能

    C#导出数据到excel如何提升性能

    这篇文章主要介绍了C#导出数据到excel如何提升性能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参...

    叶丶梓轩11132022-09-24
  • C#C# 删除字符串中的中文(实例分享)

    C# 删除字符串中的中文(实例分享)

    本文主要分享了C#删除字符串中的中文的具体实例,具有一定的参考价值,需要的朋友一起来看下吧...

    欣宇10862021-12-16