views:

74

answers:

3

This is is returning a boolean based on whether or not there are some matching IDs.

from t in getAll
select new Result
{
...             
    bool DetailsAvailable = 
        (db.SaveTrackings.Where(s => s.BundleID == t.bundleID 
                                  && s.UserID == t.userID)
                         .Count() > 0) ? true : false;
}

This is what I think understand: .Where() is returning all the entries with the matching IDs and then the .Count() is just seeing how many are there. I only feel like I half understand what we need s for.

I know what to expect from this code since it's been in use I just don't understand how it works and some of the documentation from MSDN is using some terminology that is confusing me.

All lambda expressions use the lambda operator =>, which is read as "goes to". The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block. The lambda expression x => x * x is read "x goes to x times x."

So how am I suppose to understand what my code means based on this, .Where(s "goes to" s.BundleID == t.BundleID...) so what's happening here? What does "goes to" mean? Is it comparing every ID in s to everyone one available in t? How do I understand why it's called "goes to" and what exactly is happening?

And then it gets more confusing...

The => operator has the same precedence as assignment (=) and is right-associative.

Lambdas are used in method-based LINQ queries as arguments to standard query operator methods such as Where.

When you use method-based syntax to call the Where method in the Enumerable class (as you do in LINQ to Objects and LINQ to XML) the parameter is a delegate type System.Func. A lambda expression is the most convenient way to create that delegate.

What is a delegate type System.Func<T, TResult> and how is it created with this "goes to" operator?

I can't just use code because I know that it's working, I need to understand how/why.

+2  A: 

If it helps, think of s as a variable of type SaveTracking. It's iterating over each s in your collection/table, and testing the value of its BundleID.

The t is same idea - it's like it's iterating through all the return collection from the getAll.

It's like the SQL pseudocode:

 SELECT * FROM SaveTracking INNER JOIN GetAll 
    ON BundleID AND UserID

For a deeper technical description of what's going on with lambda expressions, check out Jon Skeet's book C# In Depth. Chapter 9 , p 230. I found this book very helpful.

p.campbell
This doesn't help though because I understand that already, and having a 'think of it like this' example isn't what I needed, I'm trying to understand what exactly the computer is actually doing not what the resulting behavior is
shogun
A: 

Lambda expressions are just a way to shorten the code but it does exactly the same things as declaring a method that corresponds to the delegate type System.Func<T, TResult>

I believe that C# converts your lamba to a method in the background when you compile and it looks like this :

bool LambdaExpression(YourType s)
{
   return  s.BundleID == t.bundleID && s.UserID == t.userID;
}
StevenGilligan
+2  A: 

Maybe it would help to see this function implemented by hand:

using System;
using System.Collections.Generic;

namespace CSharpSandbox
{
    class Program
    {
        static IEnumerable<T> Where<T>(IEnumerable<T> input, Func<T, bool> predicate)
        {
            foreach (T item in input)
            {
                if (predicate(item))
                    yield return item;
            }
        }

        static void Main(string[] args)
        {
            int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            IEnumerable<int> evens = Where(numbers, n => n % 2 == 0);
            foreach (int even in evens)
            {
                Console.WriteLine(even);
            }
        }
    }
}

The construct name => someEvaluation creates an anonymous function consisting of the following parts:

  • name is simply the name of a parameter, its type is inferred from its usage. You need a name so you can refer to the argument passed in the function.
  • => is the start of your anonymous functions body, the scope of the body is a single expression.
  • someEvaluation is the body of your anonymous function composed of a single expression.

In our case, Func<T, bool> defines a function which takes a single parameter of type T and returns an output of type bool. (If we had used Func<T, U, bool>, we'd take two inputs of type T and U and return a bool. The last type parameter in the Func definition is the return value.)

You can invoke an instance of Func exactly as you invoke any other function. If the func takes params, you pass them in as expected, your parameters are bound to the variable names you defined. When you invoke the function, control flow will jump inside your function and evaluate its results.

In principle, you don't need to create a Func anonymously. You can pass in any function which has a compatible type signature, such as:

    static bool IsEven(int n)
    {
        return n % 2 == 0;
    }

    static void Main(string[] args)
    {
        int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        IEnumerable<int> evens = Where(numbers, IsEven);
        foreach (int even in evens)
        {
            Console.WriteLine(even);
        }
    }

This program produces the same output. In fact, behind the scenes, the syntax name => expression is syntax sugar; when it gets compiled, C# will produce a produce a private function with a hidden name and convert it to the format above.

Juliet
Maybe this would help too: http://stackoverflow.com/questions/2294053/explaining-functional-programming-to-object-oriented-programmers-and-less-technic/2294279#2294279
Juliet
Hold on a second. With your first example you wrote out a function. Is this just to demonstrate what is happening or is this really how this thing is implemented? Because I get what is happening I just don't get how. For example if I do a cout>> the computer tells the graphics card to spit out the text to my monitor. However I don't know HOW these things are happening, I just know that they work.
shogun
@Ryan: yes, the function above really *is* how you'd implement the Where function. Its not clear what part you don't understand. For what its worth, most C# is full of syntax sugar which can occasionally obscure the underlying implementation details. A function containing `yield return whatever` is converted into a class implementing `IEnumerable<T>`, which itself is a state machine which moves to the next step everytime you call its Enumerator's `MoveNext()` function. (...)
Juliet
(...) `foreach` is unwrapped expands into a `IEnumerator enumerator = enumerable.GetEnumerator(); try { ... } finally { enumerator.Dispose(); }`. And `parameter => expr` expands the anonymous function into a private class or sometimes a private function exactly as shown in the second code example. And `Func<T> f` is a descendant of the `Delegate` object, where you calling `f(whatever)` expands to `(T)f.Invoke(whatever)`. There's a lot of compiler magic, not all of it is interesting enough to dwell on. Now when you say "I just don't get how`, have you walked through the code with a debugger?
Juliet
Well I don't mean how I WOULD implement it, I mean how Microsoft has implemented it, is there actually code like this in existence or is it just an example to show me what's happening?
shogun
@Ryan: You should be able to view the actual source through Reflector or enabling .NET Source Stepping in Visual Studio. I can't guarantee their implementation will be particularly enlightening, because I believe they use different types of iterators optimized for traversal of different kinds of objects (i.e. an iterator for arrays, one for lists, general enumerable); and I'm not 100% sure, but they probably implement the IEnumerable<T> interface by hand rather than through the `yield` statement for various performance reasons. End result might leave you knowing less than when you started ;)
Juliet
ok thanks for all your input
shogun