1

Ok, let's say that I have some C# code that filters or restructures an incoming object (or list of objects), like so:

public Customer GetCustomer()
{
    var customer = _customerAdapter.GetCustomer();
    ModifyCustomer(customer);
    return customer;
}

private void ModifyCustomer(Customer c)
{
   //some changes to customer object
}

This works, but I'd prefer a more functional approach to this, i.e. keep incoming customer and return a new (modified one).

Is deep cloning the way to go? Is it recommended when coding in C#?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Cowborg
  • 2,645
  • 3
  • 34
  • 51
  • 1
    There's nothing built in to C#, see for example https://stackoverflow.com/questions/6569486/creating-a-copy-of-an-object-in-c-sharp, https://stackoverflow.com/questions/129389/how-do-you-do-a-deep-copy-of-an-object-in-net, and so on. Do note that this may be problematic if there's an ORM involved. – CodeCaster Jun 21 '21 at 12:06
  • Isn't this a matter of changing `void ModifyCustomer(Customer c)` to `Customer ModifyCustomer(Customer c)` and trusting that the content of `ModifyCustomer` is doing the right thing? – Enigmativity Jun 21 '21 at 12:50

2 Answers2

1

The closest built in feature is probably records and with expression:

public record Person(string FirstName, string LastName)
{
    public string[] PhoneNumbers { get; init; }
}

Person person1 = new("Nancy", "Davolio") { PhoneNumbers = new string[1] };
Person person2 = person1 with { FirstName = "John" };
JonasH
  • 28,608
  • 2
  • 10
  • 23
  • Cool! Were not there yet (C# 9), but I will definately look into it, and use it in my own project until then! – Cowborg Jun 21 '21 at 12:52
  • @Cowborg records should not require any runtime change, so should be possible to use in .net framework by setting LangVersion in the .csproj, even if this is not officially supported. – JonasH Jun 21 '21 at 13:02
0

If you can't use C# 9 then you can do something like this:

public class Consumer
{
   public readonly string FirstName;
   public readonly string LastName;

   public Consumer(string firstName, string lastName)
   {
       this.FirstName = firstName;
       this.LastName = lastName;
   }

   public Consumer WithFirstName(string firstName)
     => string.Equals(this.FirstName, firstName) 
              ? this 
              : new Consumer(firstName, this.LastName);

   public Consumer WithLastName(string lastName)
     => string.Equals(this.LastName, lastName)
              ? this
              : new Consumer(this.FirstName, lastName);
   }
}

Related dotnet blogpost

Peter Csala
  • 17,736
  • 16
  • 35
  • 75