Immutable types (classes, interfaces, records, structs) have multiple advantages. Those include, but are not limited to:
- Predictable Behavior Immutable objects exhibit predictable behavior because their state remains constant. This predictability simplifies debugging and makes the code easier to reason about, reducing the chances of subtle bugs.
- Thread Safety Immutable objects are inherently thread-safe. Since their state cannot change after creation, multiple threads can safely access them concurrently without the risk of race conditions or data corruption.
- Functional Programming Benefits Immutable objects align well with functional programming principles.
- Caching and Reusability Immutable objects can be safely cached. Once an immutable object is created, it can be shared across different parts of the codebase without worrying about unintended modifications.
- Easier Testing Testing becomes more straightforward when dealing with immutable objects. Since their behavior is consistent and their state doesn't change, you can create test cases that rely on this consistency.
- Simplified Error Handling Immutable objects are less prone to errors because their state doesn't change. This means that once you handle an immutable object correctly, you can trust its state throughout the program's execution.
This rule assumes that the code base contains only read-only types/models
unless explicitly defined otherwise, using a [Mutable]
attribute to decorate
the type. In all other cases, type of the property should be immutable.
public class SomeClass
{
public List<int> Values { get; init; }
}
Using an immutable alternative
public class SomeClass(int value)
{
public IReadOnlyList<int> Values { get; init; }
}
Decorating a model as mutable.
[Mutable]
public class SomeClass
{
public List<int> Values { get; init; }
}