how do I translate the "var result" of the lambda expression into a usable object that I can then print the result?
First off, the "lambda expression" is only the portion of the expression that is of the form a=>b
. The rest of your query is just a method call that takes a lambda as its argument.
Anyway, if I could teach people one thing about LINQ it would be this: "result" isn't the results of the query, it is the query itself.
If you want to see the results, ask the query for each result:
foreach(var item in result)
Console.WriteLine(item.ToString());
I would also appreciate an in-depth explanation of what is happening when I declare the outer => outer.Value.Frequency
Sure. We begin by working out the types of everything involved. We see that the lambda is a function which takes a KeyValuePair and returns an int, so we generate a method
static private int MyLambda(KeyValuePair<int, FrequencyAndValue> outer)
{
return outer.Value.Frequency;
}
Next we take that method and create a delegate out of it:
var result = dictionary.OrderByDescending(
new Func<KeyValuePair<int, FrequencyAndValue>, int>(MyLambda));
and rewrite the extension method call:
var result = Enumerable.OrderByDescending<KeyValuePair<int, FrequencyAndValue>, int>(
dictionary,
new Func<KeyValuePair<int, FrequencyAndValue>, int>(MyLambda));
and rewrite the var:
IOrderedEnumerable<KeyValuePair<int, FrequencyAndValue>> result =
Enumerable.OrderByDescending<KeyValuePair<int, FrequencyAndValue>, int>(
dictionary,
new Func<KeyValuePair<int, FrequencyAndValue>, int>(MyLambda));
I hope you agree that the code you typed in is a whole lot more readable than this mess. Type inference rocks.
The result is an object which represents the ability to sort this dictionary by the given key. Read that carefully: it represents the ability to sort the dictionary by that key. It does not actually do that until you ask for a result; so far, all it is is an object that says "when asked for a result, sort the dictionary by this key".
Suppose you ask for a result. How does it compute the sorted list? It asks the dictionary for each element. Then it calls MyLambda on each element, which gives back an integer, so we now have a pair of dictionary key-value pairs and integers. It then builds a list of pairs sorted on that integer. Then it hands out elements of that list one at a time, as you ask for them.
We see that the lambda is a function which takes a KeyValuePair and returns an int" - How did you determine that? I don't see it from the method return value, nor documented in the OrderByDescending().
Ah, I see the confusion; for pedagogic reasons I fibbed a bit above regarding the exact order in which the semantic analysis proceeds.
How we do this type inference is one of the more subtle and interesting parts of C#.
Here's how it works.
We see that OrderByDescending is declared as:
static IOrderedEnumerable<T> OrderByDescending<T, K>(
this IEnumerable<T> sequence,
Func<T, K> keyExtractor)
and we see we have a potential call to this method:
OrderByDescending(dictionary, o=>o.Value.Frequency)
But we do not know what T and K are. So we start by looking at everything that is NOT a lambda. Your dictionary implements IEnumerable<KeyValuePair<int, FrequencyOrValue>>
so we start by saying "T is probably KeyValuePair<int, FrequencyOrValue>
".
At this point there is nothing else we can deduce from stuff that is not lambdas so we start looking at the lambdas. We see that we have a lambda o=>o.Value.Frequency
and so far we have determined that the type of keyExtractor is Func<KeyValuePair<int, FrequencyOrValue>, K>
and we are still looking for K. So we say suppose the lambda actually was:
(KeyValuePair<int, FrequencyOrValue> o)=>{return o.Value.Frequency;}
And we ask does it bind? YES! Yes it does. We can successfully compile this lambda without error and when we do so, we see that all of its return statements return an int.
Therefore we deduce that K is int, and we now have a full type analysis of the whole thing.
This is a fairly straightforward inference; they can get much weirder. See the "type inference" archive on my blog if this subject particularly interests you.
http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx
In particular, here's a video of me explaining the stuff above plus a few other interesting cases:
http://blogs.msdn.com/ericlippert/archive/2006/11/17/a-face-made-for-email-part-three.aspx