Skip to main content
4 of 5
Fixed the typo
Peter Csala
  • 9.8k
  • 1
  • 15
  • 33

There is a special use case when the (slightly modified) second approach could be beneficial. Namely when you want to create immutable objects.

public sealed class PersonEntity
{
    public string FirstName { get; }
    public string LastName { get; }
    public int Age { get; }

    public PersonEntity(string firstName, string lastName, int age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
    }
}

By removing the setters you are not allowing the consumer of the class to alter its data after creation. In case of concurrency immutable structures can be shared safely between multiple workers without extra syncronization.

You can define with method(s) to this class as an extension to provide copy with alternative value functionality.

public PersonEntity WithFirstName(string firstName)
{
    return new PersonEntity(firstName, LastName, Age);
}

public PersonEntity WithLastName(string lastName)
{
    return new PersonEntity(FirstName, lastName, Age);
}

public PersonEntity WithAge(int age)
{
    return new PersonEntity(FirstName, LastName, age);
}

Of course you can make it a bit more generic:

public PersonEntity With(string firstname = null, string lastName = null, int? age = null)
{
    return new PersonEntity(
       firstName ?? this.FirstName, 
       lastName ?? this.LastName, 
       age ?? this.Age);

}

Usage sample:

var xy = new PersonEntity("x", "y", 15);
var xz = xy.With(lastName: "y");
var xz25 = xz.With(age: 25);

UPDATE: C# 9's record
In C# 9 there will be a new construction called record.

Declaration

public record PersonEntity
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
    public int Age { get; init; }
}

Usage

var xy = new PersonEntity { FirstName = "x", LastName = "y", Age = 15 }; 
var xz = xy with { LastName = "y" };
var xz25 = xz with { Age = 25 };
Peter Csala
  • 9.8k
  • 1
  • 15
  • 33