Skip to main content
edited body
Source Link
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""z");
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""z" };
var xz25 = xz with { Age = 25 };

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 };

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: "z");
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 = "z" };
var xz25 = xz with { Age = 25 };
Fixed the typo
Source Link
Peter Csala
  • 9.8k
  • 1
  • 15
  • 33
var xy = new PersonEntity { FirstName = "x", LastName = "y", Age = 15 }; //<-this character was wrong but I could not change without adding more text since there is a limit of minimum of 6 characters on edits. This comment should be plenty long enough to get round the silly rule. Maybe someone else can come along and delete the comment for me :)
var xz = xy with { LastName = "y" };
var xz25 = xz with { Age = 25 };
var xy = new PersonEntity{ FirstName = "x", LastName = "y", Age = 15}; //<-this character was wrong but I could not change without adding more text since there is a limit of minimum of 6 characters on edits. This comment should be plenty long enough to get round the silly rule. Maybe someone else can come along and delete the comment for me :)
var xz = xy with { LastName = "y" };
var xz25 = xz with { Age = 25 };
var xy = new PersonEntity { FirstName = "x", LastName = "y", Age = 15 }; 
var xz = xy with { LastName = "y" };
var xz25 = xz with { Age = 25 };
var xy = new PersonEntity{ FirstName = "x", LastName = "y", Age = 15)}; //<-this character was wrong but I could not change without adding more text since there is a limit of minimum of 6 characters on edits. This comment should be plenty long enough to get round the silly rule. Maybe someone else can come along and delete the comment for me :)
var xz = xy with { LastName = "y" };
var xz25 = xz with { Age = 25 };
var xy = new PersonEntity{ FirstName = "x", LastName = "y", Age = 15);
var xz = xy with { LastName = "y" };
var xz25 = xz with { Age = 25 };
var xy = new PersonEntity{ FirstName = "x", LastName = "y", Age = 15}; //<-this character was wrong but I could not change without adding more text since there is a limit of minimum of 6 characters on edits. This comment should be plenty long enough to get round the silly rule. Maybe someone else can come along and delete the comment for me :)
var xz = xy with { LastName = "y" };
var xz25 = xz with { Age = 25 };
added c# 9 support
Source Link
Peter Csala
  • 9.8k
  • 1
  • 15
  • 33
Loading
Source Link
Peter Csala
  • 9.8k
  • 1
  • 15
  • 33
Loading