0

I have tried tp understand lambda expressions for a long time(many attempts).

Inside Razor view I have a foreach loop over the ICollection<Comment> Comments where Model is of class Product.

@foreach (var comment in Model.Comments) {
            <p> @Html.DisplayFor(m => comment.TimeStamp)</p>
}

I don't understand why I can use any letter before => inside that expression and it still works. If that does not matter why do I have to write anything before =>?

How it would translate(if it was possible) to the standard method syntax?

  • 3
    It works exactly the same way method parameter names work - they can be pretty much anything. The difference is for lambda expression it cannot collide with any variable already existing in the scope it's declared in. – MarcinJuraszek May 30 '15 at 08:29

2 Answers2

2

In your example, m is the parameter to your function, which is used to pass the value of comment in to your function. However, with the lambda, you still have access to comment, which you are using directly. Just because you do not use the parameter doesn't mean you can do away with it though.

As a result, you could rewrite your code snippet as:

@foreach (var comment in Model.Comments) {
        <p> @Html.DisplayFor(m => m.TimeStamp)</p>
}
David Arno
  • 42,717
  • 16
  • 86
  • 131
  • Ok, so does `comment == m` or `comment.Equals(m)`? – fashio oihioh May 30 '15 at 08:43
  • 1
    @fashiooihioh, Unless the `Comment` class does something odd, then the answer is "both". `m` and `comment` contain the same reference to a `Comment` instance. – David Arno May 30 '15 at 08:46
  • 1
    @T.J.Crowder, I'm not familiar with `@Html.DisplayFor` specifically, but if what you say is true, my answer is wrong as I state `m` cannot be done away with, whereas you are suggesting there's an overload that takes a parameterless delegate. – David Arno May 30 '15 at 08:49
  • @DavidArno: Yeah, that comment was misleading. I was speaking of the general case of lambdas, but of course the lambda you pass has to conform to one of the signatures what you're passing it *into* supports. I'm also not familiar with `@Html.DisplayFor`, but it [seems](https://msdn.microsoft.com/en-us/library/ee407390(v=vs.118).aspx) to require at least one argument. – T.J. Crowder May 30 '15 at 08:54
1

It important to understand that lambda is in its essence anonymous function declaration.

1) I don't understand why I can use any letter before => inside that expression and it still works

m is just parameter name. You can write @Html.DisplayFor(m => m.TimeStamp) or @Html.DisplayFor(i => i.TimeStamp) and it would be (in this case! - see this) functionally equal to your code (but more efficient)

Reason why your code works is because m parameter is not used in any way and code inside lambda (which is effectively function body) is using variable declared outside the function (code after =>). This is called closure\captured variable - it's less efficient, have many pitfalls but can be extremely useful...

2) If that does not matter why do I have to write anything before =>?

Because @Html.DisplayFor method is declared to take Func<TModel, TValue> parameter which you can read as 'function which takes one argument (model) and returns single value'

3) Using normal (anonymous) method syntax:

@foreach (var comment in Model.Comments) {
            <p> @Html.DisplayFor(delegate(CommentsType c) { return c.TimeStamp; })</p>
}

....where CommentsType is type of Model.Comments property

Community
  • 1
  • 1
Michal Levý
  • 33,064
  • 4
  • 68
  • 86