tags:

views:

150

answers:

5
Func<Classification, string> test1 = c => c.Id = "x"; 
Func<Classification, string> test2 = c => { return c.Id = "x";};

I've worked with lambda's for nearly a year or so now and fairly reasonable with them, but today I was looking at NBuilder and seen a weird Func that didn't seem to match the examples. I had play anyway and it checks out but I don't understand why the above compiles let alone runs. We are doing an assignment and thus the expression doesn't evaluate to anything, right??? or not

So I thought maybe something I've missed related to lambda, so I tried something else:

    [Test]
    public void AmIGoingMad()
    {
        Assert.That(Test(),Is.Null); // not sure what to expect - compile fail?
    }

    public string Test()
    {
        string subject = "";
        return subject = "Matt";
    }

Sure enough AmIGoingMad fails and "Matt" is actually returned.

Why do we have this behavior? Where is this documented? Is it purely a syntactic shortcut?

I feel like I missed something fundamental in my understanding of lambda or even C#.

Feeling dumb.

+10  A: 

An assignment statement has a return value--that value is that which was assigned. Even C had this, so you could chain together assignments like the following:

a = b = c = d = 10;

The assignment to d has the return value of 10 which gets assigned to c, and so on.

Eric
+2  A: 

What you're seeing is assignment chaining, something that goes way back to C/C++. It's there to support this scenario:

int a = b = c = 0;

Or somewhere I actually use it:

public static IEnumerable<string> ReadLines(string filePath)
{
    using (var rdr = new StreamReader(filePath))
    {
       string line;
       while ( (line = rdr.ReadLine()) != null)  // <-----
       {
          yield return line;
       }
    }
}
Joel Coehoorn
A: 

I don't understand your question.

You post code that looks like you've misunderstood the difference between = and ==, and then explicitly comment that you want it to use = which is the assignment operator.

Let me ask you a question instead:

Why would you want or expect this to not compile?

Assert.That(Test(),Is.Null); // not sure what to expect - compile fail?

Basically, you're doing this:

String temp = Test();
Assert.That(temp, Is.Null);
Lasse V. Karlsen
+2  A: 

It works because the assignment c.Id = "x" evaluates to the value of "x". You can use this for example if you want to assign and check a value in one statement (which some people consider bad practice) like this:

string s;
if((s = SomeFunction()) != null) { \\do something with s }
Lee
+1  A: 

As others said, the assignment returns a value itself.

You could also take advantage of it like this:

private List<string> theList;
public List<string> LazyList
{
  get { return theList ?? (theList = new List<string>()); }
}
Hans Kesting
This breaks the purity assumption of property getters (no side effects).
280Z28
@280Z28 - This is a valid example of a lazy loading property. In .Net4 they've added Lazy<> to easily make this type of property threadsafe.
Pedro