Linq特取操作之ElementAt,Single,Last,First源码分析
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源码分析的更多相关文章
- Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析
Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析 一:Linq的聚合运算 1. 常见的聚合运算:Aggregate,Count, Sum, Distinct,Max, ...
- Linq分组操作之GroupBy,GroupJoin扩展方法源码分析
Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...
- Linq生成操作之DefautIfEmpty,Empty,Range,Repeat源码分析
Linq生成操作之DefautIfEmpty,Empty,Range,Repeat源码分析 Linq的四种生成运算 DefautIfEmpty,Empty,Range,Repeat 也就是给我们初始化 ...
- Linq基础操作之Select,Where,OrderBy,ThenBy源码分析
Linq基础操作之Select,Where,OrderBy,ThenBy源码分析 二:Select 它是延迟执行.yield有得一拼,因为他们都是生成了一个枚举类. if (source is TSo ...
- Linq转换操作之OfType,Cast,AsEnumerable,ToLookup源码分析
Linq转换操作之OfType,Cast,AsEnumerable,ToLookup源码分析 一:Tolookup 1. 从方法的注解上可以看到,ToLookup也是一个k,v的形式,那么问题来了,它 ...
- Linq集合操作之Intersect,Except,Union源码分析
Linq集合操作之Intersect,Except,Union源码分析 linq的集合运算 常见的集合运算有哪些? 这三个扩展方法在我们实际使用中用的还是非常多的,而且这里还涉及到了“复杂度” 无算法 ...
- Linq限定操作之All,Any,Contains源码分析
Linq限定操作之All,Any,Contains源码分析 linq的限定操作 常见的限定操作: All,Any,Contains 一:All 1. 解释: 确定序列中的所有元素是否满足条件. 从字面 ...
- Linq转换操作之ToArray,ToList,ToDictionary源码分析
Linq转换操作之ToArray,ToList,ToDictionary源码分析 一:linq中的转换运算符 1. ToArray 我们经常用在linq查询上吧. linq只能运用在IEnumerab ...
- Linq扩展最后遗留之SelectMany,Zip,SequenceEqual源码分析
Linq扩展最后遗留之SelectMany,Zip,SequenceEqual源码分析 一: AsParallel [并行化查询] 这个函数的功效就是将计算结果多线程化.[并行计算] =>[多核 ...
随机推荐
- Tkinter Toplevel
Tkinter Toplevel:顶层部件的工作,直接由窗口管理器管理的窗口.他们不必在它们上面的父widget 顶层部件的工作,直接由窗口管理器管理的窗口.他们不必在它们上面的父widge ...
- day9-IO心得
Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SSH Tws ...
- 禁止xfce4黑屏
我在ubuntu server上安装了xfce,可是每隔十分钟电脑就会黑屏.安装了xfce自带的电源管理程序.貌似不起作用.后来从网上找到如下方法: 修改/etc/X11/xorg.conf配置文件, ...
- malloc()与calloc区别 (转)
另外说明: 1.分配内存空间函数malloc 调用形式: (类型说明符*) malloc (size) 功能:在内存的动态存储区中分配一块长度为"size" 字节的连续区域.函数的 ...
- LUA和C#关于字符串中\0的处理
LUA中: local s = "hello\0\0dddddddd" print(s) --hello C#中: string s = "hello\0\0dddddd ...
- Mac 通过gem安装CocoaPods及Pod的使用
注:根据http://www.jianshu.com/p/6e5c0f78200a的文章做了部分修改 一.什么是CocoaPods CocoaPods是iOS项目的依赖管理工具,该项目源码在Githu ...
- css垂直居中方案
先介绍几种常见的垂直布局方式: 已知盒子具体宽度(宽度可以为百分比)(适用于居中浮动元素) 第一种: 给父元素相对定位,给子元素绝对定位 父布局 { position: relative; } 子布局 ...
- 【LA3211 训练指南】飞机调度 【2-sat】
题意 有n嫁飞机需要着陆.每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种.第i架飞机的早着陆时间为Ei,晚着陆时间为Li,不得在其他时间着陆.你的任务是为这些飞机安排着陆方式,使 ...
- java-tip-关于StringBuilder的使用
当我们需要拼接字符串时,通常会使用StringBuilder,这里简单分析下StringBuilder的内部结构. StringBuilder内部是一个char数组,当调用append方法连接字符串时 ...
- 541. Reverse String II 指定翻转前k个的字符串
[抄题]: Given a string and an integer k, you need to reverse the first k characters for every 2k chara ...