这里是一段 C# 代码:
class Program
{
List<string> data = new List<string>(){ "ABC", "DEF", "H" };
static void Main(string[] args)
{
var p = new Program();
}
private Program()
{
UseWhereAndAny();
UseAny();
}
private void UseWhereAndAny()
{
var moreThan2 = data.Where(m => m.Length > 2).Any();
}
private void UseAny()
{
var moreThan2 = data.Any(m => m.Length > 2);
}
}
如果您检查IL代码,您会注意到两者之间有一点不同:
.method private hidebysig
instance void UseAny () cil managed
{
.maxstack 4
.locals init (
[0] bool moreThan2
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.Collections.Generic.List`1<string> AnyWhere.Program::data
IL_0007: ldsfld class [mscorlib]System.Func`2<string, bool> AnyWhere.Program::'CS$<>9__CachedAnonymousMethodDelegate4'
IL_000c: brtrue.s IL_0021
IL_000e: ldnull
IL_000f: ldftn bool AnyWhere.Program::'<UseAny>b__3'(string)
IL_0015: newobj instance void class [mscorlib]System.Func`2<string, bool>::.ctor(object, native int)
IL_001a: stsfld class [mscorlib]System.Func`2<string, bool> AnyWhere.Program::'CS$<>9__CachedAnonymousMethodDelegate4'
IL_001f: br.s IL_0021
IL_0021: ldsfld class [mscorlib]System.Func`2<string, bool> AnyWhere.Program::'CS$<>9__CachedAnonymousMethodDelegate4'
IL_0026: call bool [System.Core]System.Linq.Enumerable::Any<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, bool>)
IL_002b: stloc.0
IL_002c: ret
}
当使用UserWhere方法时:
.method private hidebysig
instance void UseWhereAndAny () cil managed
{
.maxstack 4
.locals init (
[0] bool moreThan2
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.Collections.Generic.List`1<string> AnyWhere.Program::data
IL_0007: ldsfld class [mscorlib]System.Func`2<string, bool> AnyWhere.Program::'CS$<>9__CachedAnonymousMethodDelegate2'
IL_000c: brtrue.s IL_0021
IL_000e: ldnull
IL_000f: ldftn bool AnyWhere.Program::'<UseWhereAndAny>b__1'(string)
IL_0015: newobj instance void class [mscorlib]System.Func`2<string, bool>::.ctor(object, native int)
IL_001a: stsfld class [mscorlib]System.Func`2<string, bool> AnyWhere.Program::'CS$<>9__CachedAnonymousMethodDelegate2'
IL_001f: br.s IL_0021
IL_0021: ldsfld class [mscorlib]System.Func`2<string, bool> AnyWhere.Program::'CS$<>9__CachedAnonymousMethodDelegate2'
IL_0026: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Where<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, bool>)
IL_002b: call bool [System.Core]System.Linq.Enumerable::Any<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
IL_0030: stloc.0
IL_0031: ret
}
据我所了解,使用
Where和Any会导致额外的枚举,从而增加开销。
Single()
根本无法使用 - 它会抛出NotSupportedException()
或类似的异常。另一个例子是Take()
- 在LINQ-to-SQL中,你可以在无序的序列上使用Take()
,它将使用底层数据库的顺序(即没有ORDER BY
) - 然而,EF拒绝执行Take()
除非该序列已经排序。 - Marc Gravell