C#的接口 IEnumerable 定义了 GetEnumerator 方法,它的拓展方法是都是基于这个迭代器实现的。
当我们使用比如,First、Where等泛型方法时,会实例化一个迭代器 Enumerator 包含 属性Current,方法MoveNext()
public interface IEnumerator { bool MoveNext(); Object Current {get;} void Reset(); }
其中HashSet的MoveNext实现如下:
public bool MoveNext() { if (version != set.m_version) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_EnumFailedVersion)); } //遍历每一个slot while (index < set.m_lastIndex) { if (set.m_slots[index].hashCode >= 0) { current = set.m_slots[index].value; index++; return true; } index++; } index = set.m_lastIndex + 1; current = default(T); return false; }
比如说对HashSet使用First()尝试获取第一个元素,那么它将会生成一个迭代器,从HashSet内部维护的 Slot[] 的 index=0 处开始查找,而由于HashSet的 Slot 是基于哈希算法计算索引位置的,其中的未被哈希命中的Slot都是默认值,也就是空值。这意味着当你调用First函数时,将会从 Slot[] 的头部一直找到第一个不为空的 Slot 进行返回,也就是对 Slot[] 进行了枚举,时间复杂度是O(n)而不是O(1),效率将极大降低。
其它IEnumerable的扩展方法同理。
标签:Slot,index,set,HashSet,C#,MoveNext,泛型 From: https://www.cnblogs.com/leoric/p/16841102.html