views:

542

answers:

4

In this code from Microsoft's MVC Tutorial NerdDinners:

public class DinnerRepository {

private NerdDinnerDataContext db = new NerdDinnerDataContext();

//
// Query Methods

public IQueryable<Dinner> FindAllDinners() {
    return db.Dinners;
}

public IQueryable<Dinner> FindUpcomingDinners() {
    return from dinner in db.Dinners
           where dinner.EventDate > DateTime.Now
           orderby dinner.EventDate
           select dinner;
}

public Dinner GetDinner(int id) {
    return db.Dinners.SingleOrDefault(d => d.DinnerID == id);
}

//
// Insert/Delete Methods

public void Add(Dinner dinner) {
    db.Dinners.InsertOnSubmit(dinner);
}

public void Delete(Dinner dinner) {
    db.RSVPs.DeleteAllOnSubmit(dinner.RSVPs);
    db.Dinners.DeleteOnSubmit(dinner);
}

//
// Persistence 

public void Save() {
    db.SubmitChanges();
}

}

What does:

public Dinner GetDinner(int id) {
    return db.Dinners.SingleOrDefault(d => d.DinnerID == id);
}

the "d" mean? How does this code work? I know it it bringing back dinners where dinnerid matches id from the function parameter. I don't understand the "d goes to..." means. I know it is a lambda but I don't really get it. What is the "d" for? What does it do?

Could this have been written without the lambda here (how)?

Thank you.

+2  A: 

You need to understand lambda syntax and what it's used for.

Here's an article that does a decent job of explaining it.

However, to shortly answer your question in regards to the NerdDinner context, "d" in this context is just a parameter passed into the lamda expression that is a Dinner object.

Joseph
But how did d ever get so that it could refer to db dinners?
johnny
@johnny because one of the SingleOrDefault overloads takes an expression that is basically a Func<T> where T is a Dinner
Joseph
The official notation of the => operator is to read it as "goes to", so it's actually correct to say it like that. http://msdn.microsoft.com/en-us/library/bb397687.aspx
womp
@womp oh ok, didn't know that, will modify my answer. I still like "such that" myself, but whatever =P
Joseph
The article was helpful. Thank you. But, how does d become a dinner object?In the article: ChangeInt myDelegate = x => x * 2; and he says that "This lambda expression is an anonymous method that takes one argument x, and returns x * 2."In my context d is the argument, but I don't see anything that sends something that makes 'd' a dinner object, like this from the article:Console.WriteLine("{0}", myDelegate(5));Here a five is sent and x becomes five. In mine there's just 'd' and I see no where that "makes" d a dinner object.
johnny
Is it because my return type is Dinner and therefore d is being equated with that type (Dinner)?
johnny
@Johny I believe the return type has more to do with the SingleOrDefault function and less to do with the expression d => d.DinnerID == id. You can actually use SingleOrDefault without passing anything into it, and it will still return to you a Dinner object, it just won't be filtered as was requested. With the expression you are able to filter it down to only the Dinner you want.
Joseph
@Johny as an example you could do this: (from d in db.Dinners where d.DinnerID == id select d).SingleOrDefault(); and it would return a Dinner object. Actually with SingleOrDefault it might throw an exception if there's more than one. A better example would be FirstOrDefault() which would return the first Dinner object it found in the set.
Joseph
+2  A: 

This is similar too...

from d in db.Dinners
where d.DinnerID == id
select d

The code basically loops around the dinners returning the first Dinner or the default if none is found.

This is a case where the naming conventions used in a sample aren't always appropriate in production. Using a "d" as a local variable is usually fround upon and choosing a variable name of "dinner" would probably be more appropriate, although in this case the scope of d is so small it is clear either way, as long as you know how lambda expressions work.

David McEwing
so d here in your example "becomes" db.dinners - the whole object, right?
johnny
No, each Dinner on the list is tested separately by the expression. "The code basically loops around the dinners..."
Daniel Earwicker
+5  A: 

You should probably read up on anonymous methods.

Basically the code you are referring to can be written as an anonymous method without lamba syntax like this:

public Dinner GetDinner(int id) {    
   return db.Dinners.SingleOrDefault(delegate (Dinner d) {
                                       return d.DinnerID == id;
                                     });
}
Jimmie R. Houts
A: 

This bit of code:

d => d.DinnerID == id

Can be thought of as defining a function of type Func<Dinner, bool>.

Whatever you pass it to, this function can be called, and passed Dinner, and it will give back a bool.

void Foo(Func<Dinner, bool> f)
{
    bool result = f(new Dinner());
}

In your real example, the function SingleOrDefault will call the function you give it multiple times, passing it a different Dinner each time, and will return the Dinner for which the function returns true.

In fact, as you're using IQueryable, this is only conceptually what happens. The chances are, the code of the function is converted into SQL, and all the execution is done inside the database.

Daniel Earwicker