在使用Linq扩展时,看到这样的代码是正常的:
IEnumerable<int> enumerable = GetEnumerable();
int sum = 0;
if (enumerable != null)
{
sum = enumerable.Sum();
}
Run Code Online (Sandbox Code Playgroud)
为了提高代码质量,我编写了以下扩展方法来检查可以为空的枚举并打破linq执行.
public static IEnumerable<T> IgnoreIfEmpty<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null) yield break;
foreach (var item in enumerable)
{
yield return item;
}
}
Run Code Online (Sandbox Code Playgroud)
所以,我可以重构代码,如下所示:
var sum = GetEnumerable().IgnoreIfEmpty().Sum();
Run Code Online (Sandbox Code Playgroud)
我现在的问题:
更新: 我的目标框架是:3.5
Yuv*_*kov 40
在运行时我的扩展方法有哪些惩罚?
你的扩展方法被转换为状态机,所以它的开销很小,但这不应该是明显的.
以这种方式扩展linq是一个好习惯吗?
在您的问题中,您声明:
在使用Linq扩展时,看到这样的代码是正常的(在此处插入可枚举的null检查)
我不同意.在常见的做法表示不返回null,其中的IEnumerable<T>预期.大多数情况下,应该返回一个空集(或IEnumerable),留null到特殊的,因为空不空.这会使您的方法完全冗余.Enumerable.Empty<T>在需要的地方使用
Bas*_*Bas 29
GetEnumerable().IgnoreIfEmpty().Sum();?在这种情况下,它是有道理的.请注意,使用C#6,我们可以使用以下语法:GetEnumerable()?.Sum()返回一个int?.您可以编写GetEnumerable()?.Sum() ?? 0或GetEnumerable()?.Sum().GetValueOrDefault()获取一个默认为零的非空整数.
如果你真的关心性能,你也可以稍微重构一下你的方法,这样它就不是一个枚举器.虽然我不知道JIT编译器的"神秘"逻辑,但这可能会增加内联的机会:
public static IEnumerable<T> IgnoreIfEmpty<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null) return Enumerable.Empty<T>();
return enumerable;
}
Run Code Online (Sandbox Code Playgroud)
更一般地说,扩展Linq,我认为只要代码有意义就完全没问题.MSDN甚至有一篇关于它的文章.如果你看一下标准Where,Select在LINQ的方法,而忘记了他们曾经出现过性能优化,这些方法都是大多是一班轮方法.
w.b*_*w.b 14
您可以跳过其他扩展方法并使用null合并运算符 - 这就是它的用途,并且一次性检查可空性应该比另一个状态机更有效:
IEnumerable<int> enumerable = GetEnumerable();
int sum = 0;
sum = (enumerable ?? Enumerable.Empty<int>()).Sum();
Run Code Online (Sandbox Code Playgroud)