C# “Where”中新对象的Linq查询性能`

C# “Where”中新对象的Linq查询性能`,c#,performance,linq,lambda,compiler-optimization,C#,Performance,Linq,Lambda,Compiler Optimization,这两者之间是否存在性能差异: var listofoo=bar.Where(x=>x.Id==newguid(“sth”).toList(); 这是: var guid=newguid(“sth”); var listofoo=bar.Where(x=>x.Id==guid.toList(); ? 当bar是某种动态集时(然后将查询转换为SQL),可能不是这样 但是,如果它是一个简单的可枚举项?是的,有一个真正的区别:后者使用一次实例化字符串的引用,但前者调用每次加载字符串的lambda,就

这两者之间是否存在性能差异:

var listofoo=bar.Where(x=>x.Id==newguid(“sth”).toList();
这是:

var guid=newguid(“sth”);
var listofoo=bar.Where(x=>x.Id==guid.toList();
?

bar
是某种动态集时(然后将查询转换为SQL),可能不是这样

但是,如果它是一个简单的可枚举项?

是的,有一个真正的区别:后者使用一次实例化字符串的引用,但前者调用每次加载字符串的lambda,就像任何循环一样,每次都对条件目标部分求值,而不是在之前赋值,什么时候可以完成,什么时候编译器不知道如何优化自己

呼叫代码:

// List<Guid> source2 = source.Where((Guid x) => x == new Guid("sth")).ToList();
IL_000e: ldloc.1
IL_000f: ldsfld class [mscorlib]System.Func`2<valuetype [mscorlib]System.Guid, bool> ConsoleApp.Program/'<>c'::'<>9__29_0'
编码器的内联预分配:

// Guid guid = new Guid("sth");
IL_0046: ldstr "sth"
IL_004b: newobj instance void [mscorlib]System.Guid::.ctor(string)
IL_0050: stfld valuetype [mscorlib]System.Guid ConsoleApp.Program/'<>c__DisplayClass29_0'::guid

// source2 = source.Where((Guid x) => x == guid).ToList();
IL_0055: ldloc.1
IL_0056: ldloc.0
IL_0057: ldftn instance bool ConsoleApp.Program/'<>c__DisplayClass29_0'::'<Test>b__1'(valuetype [mscorlib]System.Guid)

在第一种方法中,构造函数调用
newguid(“…”)
,在此过程中,必须读取字符串并将其解析为128位数字(在数组中),对于
bar
的枚举器生成的每个新
x
,都会一次又一次地调用该构造函数。这一定要花点钱。在最后一个例子中,字符串只被解析一次。如果涉及
IQueryable
,那么第一个和第二个可能是等价的。如果涉及包含2个或更多条目的ienumerable,则第二个将更快。如果涉及一个空的ienumerable,第一个会更快。一切都好。祝你有美好的一天。清楚地说,我不是在谈论
AsQueryable
(因为
AsQueryable
很少有用)。我说的是
IQueryable
,比如EF核心或EF等。
// Guid guid = new Guid("sth");
IL_0046: ldstr "sth"
IL_004b: newobj instance void [mscorlib]System.Guid::.ctor(string)
IL_0050: stfld valuetype [mscorlib]System.Guid ConsoleApp.Program/'<>c__DisplayClass29_0'::guid

// source2 = source.Where((Guid x) => x == guid).ToList();
IL_0055: ldloc.1
IL_0056: ldloc.0
IL_0057: ldftn instance bool ConsoleApp.Program/'<>c__DisplayClass29_0'::'<Test>b__1'(valuetype [mscorlib]System.Guid)
// return x == guid;
IL_0000: ldarg.1
IL_0001: ldarg.0
IL_0002: ldfld valuetype [mscorlib]System.Guid ConsoleApp.Program/'<>c__DisplayClass29_0'::guid
IL_0007: call bool [mscorlib]System.Guid::op_Equality(valuetype [mscorlib]System.Guid, valuetype [mscorlib]System.Guid)
var query = listOfFoo.AsQueryable().Where(x => x == new Guid("sth")).ToList();

//  List<Guid> list = (from x in source.AsQueryable()
//      where x == new Guid("sth")
//      select x).ToList();
IL_0007: ldloc.0
IL_0008: call class [System.Core]System.Linq.IQueryable`1<!!0> [System.Core]System.Linq.Queryable::AsQueryable<valuetype [mscorlib]System.Guid>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
// (no C# code)
IL_000d: ldtoken [mscorlib]System.Guid
IL_0012: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0017: ldstr "x"
IL_001c: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type, string)
IL_0021: stloc.2
IL_0022: ldloc.2
IL_0023: ldtoken method instance void [mscorlib]System.Guid::.ctor(string)
IL_0028: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
IL_002d: castclass [mscorlib]System.Reflection.ConstructorInfo
IL_0032: ldc.i4.1
IL_0033: newarr [System.Core]System.Linq.Expressions.Expression
IL_0038: dup
IL_0039: ldc.i4.0
IL_003a: ldstr "sth"
IL_003f: ldtoken [mscorlib]System.String
IL_0044: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0049: call class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object, class [mscorlib]System.Type)
IL_004e: stelem.ref
IL_004f: call class [System.Core]System.Linq.Expressions.NewExpression [System.Core]System.Linq.Expressions.Expression::New(class [mscorlib]System.Reflection.ConstructorInfo, class [mscorlib]System.Collections.Generic.IEnumerable`1<class [System.Core]System.Linq.Expressions.Expression>)
IL_0054: ldc.i4.0
IL_0055: ldtoken method bool [mscorlib]System.Guid::op_Equality(valuetype [mscorlib]System.Guid, valuetype [mscorlib]System.Guid)
IL_005a: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
IL_005f: castclass [mscorlib]System.Reflection.MethodInfo
IL_0064: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::Equal(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.Expression, bool, class [mscorlib]System.Reflection.MethodInfo)
IL_0069: ldc.i4.1
IL_006a: newarr [System.Core]System.Linq.Expressions.ParameterExpression
IL_006f: dup
IL_0070: ldc.i4.0
IL_0071: ldloc.2
IL_0072: stelem.ref
IL_0073: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<valuetype [mscorlib]System.Guid, bool>>(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.ParameterExpression[])
IL_0078: call class [System.Core]System.Linq.IQueryable`1<!!0> [System.Core]System.Linq.Queryable::Where<valuetype [mscorlib]System.Guid>(class [System.Core]System.Linq.IQueryable`1<!!0>, class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0, bool>>)
IL_007d: call class [mscorlib]System.Collections.Generic.List`1<!!0> [System.Core]System.Linq.Enumerable::ToList<valuetype [mscorlib]System.Guid>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)