Linq特取操作之ElementAt,Single,Last,First源码分析

一:linq的特取操作

First/FirstOrDefault, Last/LastOrDefault, ElementAt/ElementAtOrDefault, Single/SingleOrDefault

二:First/FirstOrDefault 介绍

解释: 用于返回序列中的第一个值

异常: 如果当前集合没有值的话,如果你取第一个值,会抛出throw Error.NoElements();异常。

public static TSource First<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
if (list.Count > 0)
{
return list[0];
}
}
else
{
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
return enumerator.Current;
}
}
}
throw Error.NoElements();
}

===> FirstOrDefault <=====

if(list.count==0) return default(TSource)

三:Last/LastOrDefault

默认直接返回序列的最后一个元素。

我们也可以使用Func条件,返回满足指定条件的最后一个元素。

static void Main(string[] args)
{
var nums = new int[] { 4, 3, 2 };

var query = nums.LastOrDefault(i => i % 2 == 0);
}

源码:

=> throw Error.NoElements();

=> return default(TSource);

四: ElementAt/ElementAtOrDefault

ElementAtOrDefault: 这个方便就避免了我们在代码写过多的if判断。【判断是否超出索引】

如果现在用此方法,你就不需要担心这个问题了。。。

源码分析:【效率分析】

public static TSource ElementAtOrDefault<TSource>(this IEnumerable<TSource> source, int index)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
if (index >= 0)
{
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
if (index < list.Count)
{
return list[index];
}
}
else
{
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
if (index == 0)
{
return enumerator.Current;
}
index--;
}
}
}
}
return default(TSource);
}

可以看到,FCL中已经给我们做了一个“索引判断”,所以我们就不需要再代码中进行判断了,这样就方便我们更加的
关于业务逻辑。

五:Single/SingleOrDefault

解释:返回序列中满足指定条件的唯一元素;如果这类元素不存在,则返回默认值;如果有多个元素满足该条件,此方法将引发异常。【三个结果】

First:第一个元素

Single:唯一元素

class Program
{
static void Main(string[] args)
{
var nums = new int[] { 4, 3, 1, 2 };

var query = nums.FirstOrDefault(i => i % 2 == 0); //nums[2];

var query2 = nums.SingleOrDefault(i => i % 2 == 0);
}
}

我们再看源码解释:

public static TSource SingleOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
if (predicate == null)
{
throw Error.ArgumentNull("predicate");
}
TSource result = default(TSource);
long num = 0L;
checked
{
foreach (TSource current in source)
{
if (predicate(current))
{
result = current;
num += 1L;
}
}
if (num == 0L)
{
return default(TSource);
}
if (num != 1L)
{
throw Error.MoreThanOneMatch();
}
return result;
}
}

Linq特取操作之ElementAt,Single,Last,First源码分析的更多相关文章

  1. Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析

    Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析 一:Linq的聚合运算 1. 常见的聚合运算:Aggregate,Count, Sum, Distinct,Max, ...

  2. Linq分组操作之GroupBy,GroupJoin扩展方法源码分析

    Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...

  3. Linq生成操作之DefautIfEmpty,Empty,Range,Repeat源码分析

    Linq生成操作之DefautIfEmpty,Empty,Range,Repeat源码分析 Linq的四种生成运算 DefautIfEmpty,Empty,Range,Repeat 也就是给我们初始化 ...

  4. Linq基础操作之Select,Where,OrderBy,ThenBy源码分析

    Linq基础操作之Select,Where,OrderBy,ThenBy源码分析 二:Select 它是延迟执行.yield有得一拼,因为他们都是生成了一个枚举类. if (source is TSo ...

  5. Linq转换操作之OfType,Cast,AsEnumerable,ToLookup源码分析

    Linq转换操作之OfType,Cast,AsEnumerable,ToLookup源码分析 一:Tolookup 1. 从方法的注解上可以看到,ToLookup也是一个k,v的形式,那么问题来了,它 ...

  6. Linq集合操作之Intersect,Except,Union源码分析

    Linq集合操作之Intersect,Except,Union源码分析 linq的集合运算 常见的集合运算有哪些? 这三个扩展方法在我们实际使用中用的还是非常多的,而且这里还涉及到了“复杂度” 无算法 ...

  7. Linq限定操作之All,Any,Contains源码分析

    Linq限定操作之All,Any,Contains源码分析 linq的限定操作 常见的限定操作: All,Any,Contains 一:All 1. 解释: 确定序列中的所有元素是否满足条件. 从字面 ...

  8. Linq转换操作之ToArray,ToList,ToDictionary源码分析

    Linq转换操作之ToArray,ToList,ToDictionary源码分析 一:linq中的转换运算符 1. ToArray 我们经常用在linq查询上吧. linq只能运用在IEnumerab ...

  9. Linq扩展最后遗留之SelectMany,Zip,SequenceEqual源码分析

    Linq扩展最后遗留之SelectMany,Zip,SequenceEqual源码分析 一: AsParallel [并行化查询] 这个函数的功效就是将计算结果多线程化.[并行计算] =>[多核 ...

随机推荐

  1. MATLAB常用方法技巧总结

    ===================================================================================================M ...

  2. nginx实现多个域名共享80端口

    server { listen 80; server_name server8085.duchong.cn; location / { proxy_pass http://127.0.0.1:8085 ...

  3. Squid 代理服务器日志管理

    简介: Squid 服务器日志增长是很快的,如果不做处理的话,可以会由于系统限制单文件大小,而导致 Squid 服务停止,太大的日志文件也不适合分析. 一.日志配置 shell > grep ' ...

  4. Fail2ban 阻止暴力破解

    简介: Fail2ban 能够监控系统日志,匹配日志中的错误信息(使用正则表达式),执行相应的屏蔽动作(支持多种,一般为调用 iptables ),是一款很实用.强大的软件. 如:攻击者不断尝试穷举 ...

  5. Android自定义view与activity的传值

    昨晚在写团队项目的时候,遇到一个问题,直到今天早上才解决...即在自定义view"转盘"结束转动后获取结果的处理中,我是想吧值传到activity中的一个textview中的,但我 ...

  6. 【HDU5862】Counting Intersections

    题意 有n条线段,且都平行于坐标轴.对于每条线段,给出两个端点的坐标.问一共有多少个线段的交点. 分析 最最简单的扫描法了.用线段树或者树状数组都可以. 由题目可知,线段只有两种,要么平行于x轴要么平 ...

  7. 利用Fiddler对Android模拟器网络请求进行抓包

    安装使用Fiddler 下载安装Fiddler的方法这里就略过了,一路Next就行了.装好之后运行软件,正常情况这个时候我们已经可以对电脑的网络请求进行抓包了.Fiddler默认的代理地址是127.0 ...

  8. Unity中Avatar换装实现

    http://www.cnblogs.com/herenzhiming/articles/6533162.html

  9. Oracle 日志报错导致的 “没有登录” 问题

    遇到的问题是日志空间满了,导致Oracle无法登陆,但用PL/SQL登录仅会提示“没有登录” # 首先检查日志空间是否满了,并删除过期日志 rman target sysdba/password@or ...

  10. 用C语言进行最基本的socket编程

    什么是socket 你经常听到人们谈论着 “socket”,或许你还不知道它的确切含义.现在让我告诉你:它是使用 标准Unix 文件描述符 (file descriptor) 和其它程序通讯的方式.什 ...