I'm pogramming a lot with entity framework, collections and there with also usting where-conditions and order by actions. I've been asking myself this for a while, but never was able to figure it out.
Let say I've got the follwing two pieces of code;
EXAMPLE 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);
}
EXAMPLE 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)
}
The first example first does an order by on the resultset and then iterates over the collection where the second one has the order by on the moment we're going to iterate over it. Now the real question i've been wondering for a while where.. What is the difference in performance (if there is any)? And is one of the two methods better then the other one? Same with where conditons (simple and complex ones with joins), is there any notable difference?
There is no difference between the two..
Code -
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);
}
}
Generated code -
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;
}
EDIT:
Here was an interesting variation I was tempted to try.. In above case, for the query expression, compiler was smart enough to optimize the Select
away.. But what if, on the second variation, we tack on an explicit Select
. It was kind of not surprising, but still, compiler doesn't optimize away the explicit .Select
(vs explicit Select
in query expression - a requirement by compiler).
Code -
foreach (string val in letters.OrderBy(letter => letter).Select(letter => letter))
{
Console.WriteLine(val);
}
Generated code -
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);
Your first query is equivalent to
... = letters.OrderBy(letter => letter).Select(letter => letter);
And your second query is
... in letter.OrderBy(l => l)) {
Both queries are almost identical, only the first query has an additional .Select(...)
call where your select the given input, so it is pretty pointless. The C# compiler might remove the call, but you'll have to look at the generated IL to know that.
Furthermore, you first statement doesn't execute a query. .OrderBy(...)
, and most linq-statements, are query-definitions. This means that your call to .OrderBy(...)
doesn't actually execute, its a question that is not answered until your iterate over the results. So in both your versions the queries are executed when the foreach (... in <collection>)
accesses the collection it is going to iterate over.
Conclusion: the performance difference will be so small that you'll have to try very hard to even spot any real differences. Of course, that is my humble guess.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With