我使用实体框架,集合以及那里的usting where-conditions和order by actions来进行很多编程。我已经问了一段时间,但从来没有弄明白。
让我说下面有两段代码;
示例1:
// An unsorted string array.
string[] letters = { "d", "c", "a", "b" };
// Use LINQ query syntax to sort the array alphabetically.
var sorted = from letter in letters
orderby letter
select letter;
// Loop with the foreach keyword.
foreach (string value in sorted)
{
Console.WriteLine(value);
}
示例2:
// An unsorted string array.
string[] letters = { "d", "c", "a", "b" };
// Loop with the foreach keyword.
foreach (string val in letters.OrderBy(l => l))
{
console.writeline(val)
}
第一个示例首先对结果集执行一个order by,然后在我们要迭代它的那一刻迭代第二个具有顺序的集合。现在真正的问题我一直想知道......性能有什么不同(如果有的话)?并且两种方法中的一种比另一种更好吗?与条件(具有连接的简单和复杂条件)相同,是否存在显着差异?
答案 0 :(得分:4)
这两者没有区别..
代码 -
static void Main(string[] args)
{
string[] letters = { "d", "c", "a", "b" };
// Use LINQ query syntax to sort the array alphabetically.
var sorted = from letter in letters
orderby letter
select letter;
// Loop with the foreach keyword.
foreach (string value in sorted)
{
Console.WriteLine(value);
}
foreach (string val in letters.OrderBy(letter => letter))
{
Console.WriteLine(val);
}
}
生成的代码 -
private static void Main(string[] args)
{
string[] strArray1 = new string[4]
{
"d",
"c",
"a",
"b"
};
string[] strArray2 = strArray1;
if (Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate2 == null)
{
// ISSUE: method pointer
Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate2 = new Func<string, string>((object) null, __methodptr(\u003CMain\u003Eb__0));
}
Func<string, string> keySelector1 = Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate2;
foreach (string str in (IEnumerable<string>) Enumerable.OrderBy<string, string>((IEnumerable<string>) strArray2, keySelector1))
Console.WriteLine(str);
string[] strArray3 = strArray1;
if (Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate3 == null)
{
// ISSUE: method pointer
Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate3 = new Func<string, string>((object) null, __methodptr(\u003CMain\u003Eb__1));
}
Func<string, string> keySelector2 = Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate3;
foreach (string str in (IEnumerable<string>) Enumerable.OrderBy<string, string>((IEnumerable<string>) strArray3, keySelector2))
Console.WriteLine(str);
}
[CompilerGenerated]
private static string \u003CMain\u003Eb__0(string letter)
{
return letter;
}
[CompilerGenerated]
private static string \u003CMain\u003Eb__1(string letter)
{
return letter;
}
修改强>
这是一个有趣的变化我试图尝试..在上面的情况下,对于查询表达式,编译器足够聪明,可以优化Select
..但是,如果,在第二个变体,我们在明确的Select
。这有点不足为奇,但编译器仍然没有优化显式.Select
(与查询表达式中的显式Select
- 编译器的要求)。
代码 -
foreach (string val in letters.OrderBy(letter => letter).Select(letter => letter))
{
Console.WriteLine(val);
}
生成的代码 -
string[] strArray4 = strArray1;
if (Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate6 == null)
{
// ISSUE: method pointer
Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate6 = new Func<string, string>((object) null, __methodptr(\u003CMain\u003Eb__2));
}
Func<string, string> keySelector3 = Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate6;
IOrderedEnumerable<string> orderedEnumerable = Enumerable.OrderBy<string, string>((IEnumerable<string>) strArray4, keySelector3);
if (Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate7 == null)
{
// ISSUE: method pointer
Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate7 = new Func<string, string>((object) null, __methodptr(\u003CMain\u003Eb__3));
}
Func<string, string> selector = Program.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate7;
foreach (string str in Enumerable.Select<string, string>((IEnumerable<string>) orderedEnumerable, selector))
Console.WriteLine(str);
答案 1 :(得分:2)
您的第一个查询等同于
... = letters.OrderBy(letter => letter).Select(letter => letter);
你的第二个问题是
... in letter.OrderBy(l => l)) {
两个查询几乎完全相同,只有第一个查询有一个额外的.Select(...)
调用,你选择给定的输入,所以这是毫无意义的。 C#编译器可能会删除该调用,但您必须查看生成的IL才能知道这一点。
此外,您的第一个语句不会执行查询。 .OrderBy(...)
和大多数linq语句都是查询定义。这意味着您对.OrderBy(...)
的调用实际上并未执行,而这个问题在您对结果进行迭代之前无法解答。因此,在您的两个版本中,当foreach (... in <collection>)
访问要迭代的集合时,将执行查询。
结论:性能差异很小,你必须非常努力地发现任何真正的差异。当然,这是我的谦虚猜测。
答案 2 :(得分:0)
我能看到的唯一区别是,Iterator
在foreach
之前创建(未执行)的第一个代码中,并将它存储在局部变量中。在第二个代码中foreach
直接调用迭代器上的GetEnumarator
方法而不是局部变量。但是对于性能而言,这并没有任何区别。除此之外,由于可读性,我更倾向于第二种。