建站宝盒视频,买网站模板,百姓网地址怎么创建,wordpress上传中文图片概要
本文主要分析Linq中Take带Range参数的重载方法的源码。对于其中的一些关于Range或序列的新概念#xff0c;不再赘述#xff0c;请参看C# Linq源码分析之Take #xff08;一#xff09;
源码分析
基于Range参数的Take重载方法#xff0c;主要分成两部分实现#x…概要
本文主要分析Linq中Take带Range参数的重载方法的源码。对于其中的一些关于Range或序列的新概念不再赘述请参看C# Linq源码分析之Take 一
源码分析
基于Range参数的Take重载方法主要分成两部分实现一部分是Range中的开始和结束索引都是正数的情况例如取第一个到第三个元素的情况另一部分是开始或结束索引中有倒数的情况例如取倒数第三个到倒数第一个的情况。
本文着重分析Range中的正数情况。
public static IEnumerableTSource TakeTSource(this IEnumerableTSource source, Range range)
{if (source null){ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);}Index start range.Start;Index end range.End;bool isStartIndexFromEnd start.IsFromEnd;bool isEndIndexFromEnd end.IsFromEnd;int startIndex start.Value;int endIndex end.Value;Debug.Assert(startIndex 0);Debug.Assert(endIndex 0);if (isStartIndexFromEnd){if (startIndex 0 || (isEndIndexFromEnd endIndex startIndex)){return EmptyTSource();}}else if (!isEndIndexFromEnd){return startIndex endIndex? EmptyTSource(): TakeRangeIterator(source, startIndex, endIndex);}return TakeRangeFromEndIterator(source, isStartIndexFromEnd, startIndex, isEndIndexFromEnd, endIndex);
}
检查源序列是否为空如果为空直接抛出异常获取Range的启始和结束的索引值以及索引值是正数还是倒数的bool值如果开始索引值是倒数以下几种情况返回空序列 a开始索引是^0 倒数第0个显然不合理 bRange形如 ^1… ^3的情况假设有10个元素 ^1… ^3相当于取从第10个到第7个显然是不合理。应该是从第7个到第10个 cRange形如 ^2 … ^2因为开始和结束索引相同中间没有间隔元素该种情况也不合理在Range中的开始和结束索引都不是倒数的情况下如果开始索引大于结束索引即Range形如2…1返回空序列否则调用TakeRangeIterator方法完成具体取值操作对于合理的Range倒数情况例如形如 ^3… ^1 3… ^1 或 ^3 … 10 这些情况执行最后的TakeRangeFromEndIterator方法。
TakeRangeIterator方法
TakeRangeIterator方法用于处理Range中的开始和结束索引都是正数的情况。该方法位于Take.SizeOpt文件中。通过yield return/break的方式管理迭代过程。
private static IEnumerableTSource TakeRangeIteratorTSource(IEnumerableTSource source, int startIndex, int endIndex)
{Debug.Assert(source ! null);Debug.Assert(startIndex 0 startIndex endIndex);using IEnumeratorTSource e source.GetEnumerator();int index 0;while (index startIndex e.MoveNext()){index;}if (index startIndex){yield break;}while (index endIndex e.MoveNext()){yield return e.Current;index;}
}创建迭代器e采用using方式在函数执行完成后自动释放内存空间如果Range中的索引数据和source序列中的元素个数不匹配例如指定从第三个元素开始取但是数列里面只有两个元素返回yield break关闭状态机注意此种情况并不会抛出越界异常按照索引范围通过迭代器e取值创建状态机通过yield return方式返回。
TakeRangeFromEndIterator方法
TakeRangeIterator方法用于处理Range中的开始和结束索引存在倒数的情况。该方法位于Take.cs文件中。通过yield return/break的方式管理迭代过程。
该方法篇幅较长将在C# Linq源码分析之Take 三中详细分析其源码。