1

I know that this code is not good and maybe it's stupid question but can anybody explain me why it works in this way?

I have this simple class

public class Customer
{
    public string Name { get; set; }
}

And I have next method with Action delegate

private Customer GetCustomer(Action<Customer> action)
{
    var model = new Customer { Name = "Name 1" };
    action?.Invoke(model);

    return model;
}

Then I execute this method with delegate and write into console model.Name

var model = GetCustomer(c => c = new Customer { Name = "Name 2" });
Console.WriteLine(model.Name);

I expected to get "Name 2". But I get "Name 1" - which is value of the class defined inside method. I understand that to get what I want - I could write code in this way:

var model = GetCustomer(c => c.Name = "Name 2");
Console.WriteLine(model.Name);

And everything will be ok. But why my first implementation doesn't work? I would be thankful a lot if somebody explain me this.

driconmax
  • 956
  • 1
  • 18
  • 32
Nikolay
  • 155
  • 2
  • 10

4 Answers4

3

c in your lambda is only assigning to the parameter, its not assinging it back to model in GetCustomer.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
1

Lambda expression in your case compiles into a method.
This is the same, why this code won't change c.Name:

// code below is equivalent of
// c => c = new Customer { Name = "Name 2" }
private void Foo(Customer c)
{
    // c will be changed inside method,
    // but will remain unchanged outside it
    c = new Customer { Name = "Name 2" };
}
Dennis
  • 37,026
  • 10
  • 82
  • 150
0
var model = GetCustomer(c => c.Name = "Name 2");

instead of:

var model = GetCustomer(c => c = new Customer { Name = "Name 2" });

Why? Because you want to do the changes on the same instance transferred in the new function (implements the delegate). If you create a new instance of Customer in new function (c) then it would do the changes on the new instance of Customer that won't be valid when c ends.

Same here but with List.

Community
  • 1
  • 1
elirandav
  • 1,913
  • 19
  • 27
0

In your lambda expression, you are just saying that c and model are pointing to the same reference. And then you are changing the reference of c. At the end model is still referencing to the previous instance. This is the equivalent code of what you are trying to do:

var model = new Customer { Name = "Name 1" };
var c = model;
c = new Customer { Name = "Name 2" };

But, model.Name is still Name1.

You can change your code as if you want to change one of hte properties:

 var model = GetCustomer(c => c.Name = "Name2");
 Console.WriteLine(model.Name);
Farhad Jabiyev
  • 26,014
  • 8
  • 72
  • 98