我们先去看看公开的.Net4.0的源程序中IEnumerable、IEnumerable、IEnumerator和IEnumerator这四个接口是如何声明的: 需加微信交流群的,请加小编微信号...但是,如果您选择执行此操作,则应确保没有调用方依赖于Reset功能。 迭代器工作的原理是:先调用MoveNext()方法,然后读取Current得到元素,直到MoveNext返回false。...其次,我们要把object Current改成 IEnumerator.Current,这个是实现迭代器的关键。返回元素。...通过观察,发现迭代器主要就是返回一个元素对象,而StudentColletion里面的students元素集是List的,本身就能枚举,我们能不能利用这个不用专门写迭代器来实现枚举呢?...二、接口IEnumerable实现 如果我们想写一个通用的可foreach的类,用到泛型: class MyCollection { public List<
我在写一个简单的功能,需要将两个不同的数组合并到一起,但是我的功能只是做只读,如果合并的方法需要申请额外的内存空间,将降低性能。...本文写了一个简单的方法,通过判断下标的方法做遍历多个数组组合在一起,通过判断当前获取的下标在对应哪个数组下标范围内,返回对应数组的元素 合并多个数组或列表有多个不同的方法,但是我找到的方法都需要额外申请内存空间...,需要做一次数组元素复制,相对性能比较差,如果是做只读,功能和 Span 相反,那么可以通过遍历的数组下标判断 下面方法可以在项目用,做法很简单,看代码也就知道 using System; using...} IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator();...} IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator();
如果指定的是一个绝对路径(比如“c:\foobar”),即Path.IsPathRooted方法返回True。 如果指定的路径指向一个隐藏文件。...方法时,如果指定的路径指向一个具体的目录,那么该方法会返回一个类型为PhysicalDirectoryContents的对象。...(); IEnumerator IEnumerable.GetEnumerator(); } 四、NotFoundDirectoryContents 如果指定的路径并不指向一个存在的目录,或者指定的是一个绝对路径...这是一个公共类型,如果我们具有监控物理文件系统变化的需要,可以直接使用这个类型。...当我们调用PhysicalFileProvider的GetFileInfo方法时,如果指定的文件存在,返回的是描述该文件的PhysicalFileInfo对象。
所以如果要根据 ConditionalWeakTable 来实现弱引用集合那么需要自己记录集合中的所有的 Key,而这样的话我们依然需要自己实现一个用来记录所有 Key 的弱引用集合,相当于鸡生蛋蛋生鸡的问题...设计原则 在设计此类型的时候,有一个非常大的需要考虑的因素,就是此类型中的元素个数是不确定的,如果设计不当,那么此类型的使用者可能写出的每一行代码都是 Bug。...你可以参考我的另一篇博客了解设计这种不确定类型的 API 的时候的一些指导: 如何为非常不确定的行为(如并发)设计安全的 API,使用这些 API 时如何确保安全 总结起来就是: 必须提供一个单一的方法...,能够完成一些典型场景下某一时刻确定性状态的获取 绝不能提供一些可能多次调用获取状态的方法 那么这个原则怎么体现在此弱引用集合的类型设计上呢?...然而类型既然已经开放出去给大家使用了,那么这就非常危险。关键是这不是一个并发场景,于是开发者可能更难感受到在同一个上下文中调用两个方法将得到不确定的结果。
在.NET6中微软新增了 TryGetNonEnumeratedCount 方法,让我们可以计算可枚举类型元素的总数。...() { throw new NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator...throw new NotImplementedException(); } } 运行上面的代码会发现e.Count()能够执行,但是u.Count()报错,这是LINQ内部实现造成的...为了解决这个问题我们就需要使用TryGetNonEnumeratedCount方法,如果可以快速计数,该方法将返回true并将计数作为out变量返回。...因此建议在代码中始终使用如下方式获取可枚举类型的元素总数: if (!
IEnumerable是所有可迭代非范型类的基础接口。IEnumerable包括一个方法GetEnumerator方法,方法返回一个IEnumerator。...IEnumerator是所有非范型迭代器的基础接口。foreach语句隐藏了C#迭代器的复杂实现。推荐使用foreach代替直接操作迭代器。 迭代器可以读取集合中的数据,但是不能从底层修改集合。...如果MoveNext之后position超出了集合的范围,MoveNext将返回false。 通过调用Reset将Current重置到第一个元素之前。...,foreach是一种语法糖,简化了遍历其中的具体实现。...被遍历的类通过实现IEnumerable接口和实现一个IEnumerator枚举器实现遍历功能。
C#12中引入了新的语法糖来创建常见的集合。并且可以使用..来解构集合,将其内联到另一个集合中。 支持的类型 数组类型,例如 int[]。...集合表达式使用 以下展示了如何使用集合表达式 static void Main(string[] args) { List names1 = ["one", "two"];...以下是个例子 [CollectionBuilder(typeof(LineBufferBuilder), "Create")] public class LineBuffer : IEnumerable...() => _buffer.AsEnumerable().GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _buffer.GetEnumerator...LineBufferBuilder.Create方法必须返回 LineBuffer 对象,并且必须采用 ReadOnlySpan 类型的单个参数。
今天给大家分享一下yield关键字的用法。yield return 返回集合不是一次性返回所有集合元素,而是一次调用返回一个元素。具体如何使用yield return 返回集合呢?...} } 与平常return比较 上面我们看到了yield return 的使用方法,那么这个与return返回集合有什么区别呢?...通过代码的运行结果,我们可以看到这里返回的结果 yield return 和comment return是分成两边的。先执行完一个然后开始执行另外一个。不干涉。...我们看这个运行结果,这里yield return 和comment return 的输出完全交替了。这里说明是一次调用就返回了一个元素。...其中主要的方法是迭代器方法MoveNext()。
” 的公共定义,因此 foreach 语句不能作用于 “Cat” 类型的变量,由此错误提示我们可以得知如果 Cat 类型可以被 foreach 遍历,那么 Cat 类就必须实现 GetEnumerator...但是我们目前并不知道 GetEnumerator 方法的返回值类型和 Current 属性是否是只读的,这种情况我们该怎么办呢?...此时我们可以查看已经支持 foreach 遍历的类型是怎么做的,下面的代码段展示了 string 类型是如何实现的(只列出了关键代码)。...() { return new CatEnumerator(); } } 我们已经添加了数据对象,那么 foreach 是如何访问到这个数据的呢?...小技巧:在 c# 中如果要查看某个类型是否支持 foreach 我们可以查看还类型和该类型的迭代计数器是否都实现了 IEnumerable 接口,因为 IEnumerable 接口中的就包含了 foreach
var str="mushroomsir"; str.Substring(0, 6) c#中的string是不可变的,Substring(0, 6)返回的是一个新字符串值,而原字符串在共享域中是不变的。...我们平常使用的数据结构都是采用可变模式来实现的,那怎么实现一个不可变数据结构呢!...() { yield break; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }...() { return this.GetEnumerator(); } } 入栈时会实例化一个新栈对象 将新值通过构造函数传入,并存放在新对象Head位置,旧栈对象放在在Tail位置引用 出栈时返回当前栈对象的...Net提供的不可变集合 不可变队列,不可变列表等数据结构如果都自己实现工作量确实有点大。幸好的是Net在4.5版本已经提供了不可变集合的基础类库。
编译器隐式调用 GetEnumerator 方法,此方法返回 IEnumerator。 GetEnumerator 方法通过使用 yield return 语句每次返回 1 个字符串。...Push 方法将值分配给类型为 T 的数组。 GetEnumerator 方法通过使用 yield return 语句返回数组值。...必须存在从 yield return 语句中的表达式类型到迭代器返回的 IEnumerable 类型参数的隐式转换。 在 C# 中,迭代器方法不能有任何 in、ref 或 out 参数。...技术实现 即使将迭代器编写成方法,编译器也会将其转换为实际上是状态机的嵌套类。 只要客户端代码中的 foreach 循环继续,此类就会跟踪迭代器的位置。...避免在 foreach 循环的第一次迭代之前完全加载大型列表。 一个示例是用于加载一批表格行的分页提取。
好的,回到今天的主题:IEnumerable和IEnumerator。目前我们知道它俩是不一样的东西了,至少从单词层面(ง •_•)ง。那么在 DotNET 中,它们扮演着怎么样的角色呢?...那么这种具有了可迭代能力的对象有什么好处呢? foreach,没错,它可以享受foreach的语法糖啦。...IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); }...语法糖就可以迭代它啦,然后foreach in 出来的每一个对象的类型是什么样子的呢?...(for循环中的ball)。 ? 是的,它是Ball类型,那么那个BallEnum类型呢? 它隐藏起来了,我们根本看不见啦。
类a包含GetEnumerator方法和一个可枚举类型的迭代器,该可枚举类型迭代器内部又自动实现了GetEnumerator方法和一个可枚举类型 要想遍历该类a,类a的GetEnumerator方法需获取可枚举类型的...但即使不实现GetEnumerator方法,也能实现枚举 a、实现总类的GetEnumerator方法:迭代器方法ib内自动创建了一个枚举器和一个GetEnumerator方法,如果实现总类的GetEnumerator...也可枚举的方法:如果不实现总类的GetEnumerator方法,Main方法直接采用IEnumerable类型的迭代器(内有GetEnumerator方法),那么就不需要总类的GetEnumerator...在一个类中产生多个可枚举类型,那么就不能能实现GetEnumerator方法,因为可枚举类型的GetEnumerator方法主体有固定格式,无法再次写个GetEnumerator方法,那样就会重名,且...Main方法调用的也不知是哪个正确的GetEnumerator方法 一个类产生多个可枚举类型,而是采用不实现GetEnumerator的方法,Main方法直接调用返回可枚举类型的迭代器,即上文的“b、不实现
设计Enumerable和Queryable两套接口的原因是为了区别对待LINQ to OBJECTS、LINQ to SQL,两者对于查询的处理在内部使用的是完全不同的机制。...可以发现以上方式实现的排序至少存在两个问题: 1)可扩展性太低,如果存在新的排序要求,就必须实现新的比较器。 2)对代码的侵入性太高,为类型继承了接口,增加了新的 方法。...那么有没有一种方法,即使类型只存在自动实现的属性,也能满足多方面的排序要求呢?答案是使用LINQ。LINQ提供了类似于SQL的语法来实现遍历、筛选与投影集合的功能。借助于LINQ的强大功能。 ...建议31、在LINQ查询中避免不必要的迭代 无论是SQL查询还是LINQ查询,搜索到结果立刻返回总比搜索完所有的结果再将结果返回的效率要高。现在简单来创建一个自定义的集合类型来说明。...与First一样,它满足条件以后,会从当前的迭代过程直接返回,而不是等到整个迭代过程完毕再返回。如果一个集合包含了很多的元素,那么这种查询会为我们带来可观的时间效率。
实现了这个接口的类可以使用Foreach关键字进行迭代(迭代的意思是对于一个集合,可以逐一取出元素并遍历之)。实现这个接口必须实现方法GetEnumerator。...如何实现一个继承IEnumerable的类型? 实现一个继承IEnumerable的类型等同于实现方法GetEnumerator。...想知道如何实现方法GetEnumerator,不妨思考下实现了GetEnumerator之后的类型在Foreach之下的行为: 可以获得第一个或当前成员 可以移动到下一个成员 可以在集合没有下一个成员时退出循环...实现方法GetEnumerator GetEnumerator方法需要一个IEnumerator类型的返回值,这个类型是一个接口,所以我们不能这样写: return new IEnumerator();...使用yield关键字实现方法GetEnumerator 如果iterator本身有实现IEnumerator接口(本例就是一个数组),则可以有更容易的方法: public IEnumerator
枚举器和可枚举类型 为什么数组可以使用 foreach 呢?因为数组可以提供一个枚举器(enumerator)对象。枚举器对象可以依次返回数组元素。...获取一个对象的枚举器可以调用对象的 GetEnumerator 方法。实现了 GetEnumerator 方法的对象称为可枚举(enumerable)对象。...foreach 语句就是用来配合可枚举类型一起使用的,他会执行下列行为: 调用 GetEnumerator 方法获取对象的枚举器 从枚举器请求每一项作为迭代变量(iteration variable)...current = (int)ie.Current; Console.WriteLine(current); } } } IEnumerable 可枚举类型是指实现了...泛型与非泛型版本的主要区别是: IEnumerable 接口的 GetEnumerator 方法要返回实现 IEnumerator 接口的枚举器实例 泛型版本的 Current 属性返回的不是 object
不过在这之前,我们先来看看我们经常使用的Array和ArrayList是如何实现的,从而来指导我们如何正确使用Array和ArrayList。...(this); } 同Array不同的是,GetEnumerator方法被定义成virtual,所以对于Arraylist来说,它也不可以利用Inlining的编译优化获得performance上的提升...、返回类型为Employee的Current属性。...通过输出我们可以看到While循环调用的是返回类型是Employee的Current 属性,而for each循环仍然使用的是返回类型是Object的Current 属性。...其实这是无法避免的,因为for each会把获得的Enumerator转换成对应的接口类型IEnumerator,所以调用的永远是IEnumerator中定义的返回类型为object的Current属性
本例子实现了如何自定义线性节点集合,具体代码如下: using System; using System.Collections; using System.Collections.Generic;...{ return new LineNodeEnumerator(this.firstLineNode); } IEnumerator IEnumerable.GetEnumerator...() { return this.GetEnumerator(); } public LineNode this[int index...,从而形成链接的节点; ②本示例完全由博主原创,转载请注明来处。...示例下载地址:https://pan.baidu.com/s/1eS9UIzS (请使用VS2015打开,如果为其他版本,请将Program.cs中的内容复制到自己创建的控制台程序中)