C# 9 新特性 —— 增强的 foreach

Intro

在 C# 9 中增强了 foreach 的使用,使得一切对象都有 foreach 的可能

我们来看一段代码,这里我们试图遍历一个 int 类型的值

思考一下,我们可以怎么做使得上面的代码编译通过呢?

迭代器模式

迭代器模式,提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

迭代器模式是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。

foreach 其实是一个迭代器模式的语法糖,用来遍历一个集合中的数据,foreach 可以使用 while 来实现,比如下面这个示例:

var enumerable = Enumerable.Range(1, 10).ToArray();
foreach (var i in enumerable)
{
Console.WriteLine(i);
}

使用 while 重写之后类似下面这样的代码:

var enumerator = enumerable.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}

c# 中的集合基本都实现了迭代器模式,可以直接使用 foreach 来遍历,对于自定义的类型想要支持 foreach 可以实现 IEnumerableIEnumerable<T>,对于没有实现迭代器的代码,是不是可以用 foreach

Enumerator

我们再来看开篇提到的问题,怎么实现支持 foreach

从上面 VS 的提示我们可以看得出来,如果一个类型想要支持 foreach,有三种方式可以实现:

  1. 实现 IEnumerable
  2. 实现 IEnmuerable<T>
  3. 添加 GetEnumerator 方法,方法返回值类型需要有 Current 属性和 MoveNext 方法,可以参考这个 IEnumerator,返回类型可以直接实现 IEnumeratorIEnumerator<T>

那么如果是一个别人封装的类型,能否支持 foreach 呢,从 C# 9 之后就可以了,可以添加一个 GetEnumerator 的扩展方法,类似于下面

public static class ForEachExtensions
{
public static IEnumerator<char> GetEnumerator(this int num)
{
return num.ToString().GetEnumerator();
}
}

此时如果是使用 C# 9 就可以编译通过了,如果手动设置了 LangVersion,需要修改为 9,否则会得到类似下面这样的错误

添加使用扩展方法,并启用 C# 9 语法:

More

有了这个功能之后,一切类型都是可以 foreach 的,没有实现迭代器模式的类型,只需要实现一个扩展方法就可以了

迎接 C# 9 ,万物皆可 foreach ~~

Reference

C# 9 新特性 —— 增强的 foreach的更多相关文章

  1. 使用 HTML5 History 新特性增强 Ajax 的体验(转)

    一. 场景再现 如大家熟知,Ajax 可以实现页面的无刷新操作,但会造成两个与普通页面操作(有刷新地改变页面)有着明显差别的问题—— URL 没有修改以及无法使用前进.后退按钮.例如常见的 Ajax ...

  2. C# 9 新特性 —— 增强的模式匹配

    C# 9 新特性 -- 增强的模式匹配 Intro C# 9 中进一步增强了模式匹配的用法,使得模式匹配更为强大,我们一起来了解一下吧 Sample C# 9 中增强了模式匹配的用法,增加了 and/ ...

  3. jdk1.5出现的新特性---->增强for循环

    import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; ...

  4. Java12新特性 -- 增强G1,自动返回未用堆内存给操作系统

    Java 12 中增强了 G1 垃圾收集器关于混合收集集合的处理策略,这节主要介绍在 Java 12 中同时也对 G1垃圾回收器进行了改进,使其能够在空闲时自动将 Java 堆内存返还给操作系统,这也 ...

  5. Java JDK5新特性-增强for

    2017-10-31 00:02:16 格式: for(元素数据类型 变量:数组或者Collection集合) { 使用变量即可,该变量即是元素 } int arr[] = {1,2,3,4,5}; ...

  6. C# 6.0/7.0 的新特性

    转眼C#语言都已经迭代到7.0版本了,很多小伙伴都已经把C# 7.0 的新特性应用到代码中了,想想自己连6.0的新特性都还很少使用,今天特意搜集了一下6.0和7.0的一些新特性,记录一下,方便查阅. ...

  7. JDK5的新特性之 增强for

      package cn.itcast.day19.foreach; import java.util.ArrayList; import java.util.Collection; import j ...

  8. Oracle 11g新特性延迟段创建和truncate的增强

    下面测试Oracle 11g开始的新特性truncate的增强和延迟段空间创建. Oracle从11g开始,当用户创建一张空表的时候不会先分配段和空间,只有当对这张表插入第一行数据的时候才分配段和空间 ...

  9. Spring4.1新特性——Spring缓存框架增强(转)

    目录 Spring4.1新特性——综述 Spring4.1新特性——Spring核心部分及其他 Spring4.1新特性——Spring缓存框架增强 Spring4.1新特性——异步调用和事件机制的异 ...

随机推荐

  1. Jmeter(三十) - 从入门到精通 - Jmeter Http协议录制脚本工具-Badboy3(详解教程)

    1.简介 Badboy为方便自动化数据灵活性,以及脚本的重用,减少工作量:为此提供了脚本参数化的功能,这一篇文章宏哥以度娘搜索的关键字"北京-宏哥"进行参数化为例,宏哥带领你们实战 ...

  2. 红黑树、TreeMap、TreeSet

    事先声明以下代码基于JDK1.8版本 参考资料 大部分图片引自https://www.jianshu.com/p/e136ec79235c侵删 https://www.cnblogs.com/skyw ...

  3. Java数据结构(十三)—— 二叉排序树(BST)

    二叉排序树(BST) 需求 给定数列{7,3,10,12,5,1,9},要求能够高效的完成对数据的查询和添加 思路三则 使用数组,缺点:插入和排序速度较慢 链式存储,添加较快,但查找速度慢 使用二叉排 ...

  4. Docker学习—Stack

    前言: 前一篇了解Docker使用Swarm集群部署方式,并创建服务到Swarm集群中:如果在集群部署过程中存在大量服务部署.编排那么该如何处理呢? 那么就需要了解Docker Stack了. 1.D ...

  5. Python中函数的参数带星号是什么意思?

    参数带星号表示支持可变不定数量的参数,这种方法叫参数收集. 星号又可以带1个或2个,带1个表示按位置来收集参数,带2个星号表示按关键字来收集参数. 1.带一个星号的参数收集模式: 这种模式是在函数定义 ...

  6. PyQt学习随笔:ListView控件增加列表项

    ListView控件如果需要增加列表项,就是在对应数据存储中插入项,这又分两种情况,一种是已知列表数据存储,一种是未知数据存储.如果是未知数据存储,可以通过: ListView控件名.model() ...

  7. ADB常用的命令

    ADB常用的命令: 1)adb devices---获取设备列表及设备状态 2)adb get-state---获取设备的状态 设备的状态有 3 钟,device.offline.unknown. d ...

  8. Day9 python高级特性-- 列表生成式 List Comprehensions

    Python内置的非常简单却强大的可以用来创建list的生成式.    私理解为,就是for循环出来的结果搞成个list~~~~    要生成顺序增量list可以使用list(range(x,y))来 ...

  9. oracle DG搭建

    Oracle DG 搭建1. 环境 OS IP hostname db_name DB_UNIQUE_NAME主库 RHEL 5.4 192.168.12.20 edgzrip1.oracle.com ...

  10. Cisco Packet Tracer NAT模拟实验

    Cisco Packet Tracer NAT模拟实验 by: 铁乐猫 date: 2020-09-22 cisco packet tracer : 7.2.2 NAT简介 NAT允许将私有IP地址映 ...