How to create immutable objects in C# 6
February 11, 2016 3 Comments
In C#5 you would write a Person class with immutable properties with getters as follows:
public class Person { private readonly string _name; private readonly int _age; public Person(string name, int age) { _name = name; _age = age; } public string Name { get { return _name; } } public int Age { get { return _age; } } }
The readonly keyword will make sure that the private properties can only be assigned from the constructor. If try the following…
public int Age { get { return _age; } set { _age = value; } }
…you’ll get a compiler error:
“A readonly field cannot be assigned to (except in a constructor or a variable initializer)”
A more simple way to achieve the same might be the “private set” construction:
public class Person { public int Age { get; private set; } public string Name { get; private set; } public Person(string name, int age) { Name = name; Age = age; } }
However, the Age and Name fields can still be modified within the Person class:
public string Greet() { Name = "Jill"; return string.Format("Hello from {0}", Name); }
You’ll probably guess what the following will output:
static void Main(string[] args) { Person p = new Person("John", 28); Console.WriteLine(p.Greet()); Console.ReadKey(); }
That’s right, “Hello from Jill” which is a bit unexpected from the caller’s point of view.
C#6 comes to the rescue in the following form:
public class Person { public int Age { get; } public string Name { get;} public Person(string name, int age) { Name = name; Age = age; } }
The Age and Name fields can be set in the constructor but not anywhere else. The Greet() method will fail with the following compiler error:
“Property indexer ‘Person.Name’ cannot be assigned to — it is read only”
View all various C# language feature related posts here.
Here is a Delphi style, how to manage accessibility of class propertes and methods. Used mostly in visual classes hierarchy. The idea is to use “implementation class” and “usage” class-descendant. This child class frequently contains only properties with tuned accessors.
///
/// Base class to declare fields, properties and all methods.
///
class CustomPerson
{
public string Name { get; private set; }
public int Age { get; private set; }
protected int Weight { get; set; }
public CustomPerson(string name, int age)
{
Name = name;
Age = age;
Weight = 55;
}
}
///
/// Child class to only restrict or expand visibility of properties and methods.
///
public class Person : CustomPerson
{
public new int Weight { get { return base.Weight; } }
public Person(string name, int age) : base(name, age)
{ }
}
Hi Andras,
Have you tried doing C# 6 immutable objects with Entity Framework (6 or 7)? If EF can handle it, that’d be great news for DDD developers!
Hi Ivan, no, not yet. I’ve only recently started exploring C# 6, I haven’t got that far yet. //Andras