To create an immutable object you need to follow some simple rules: Don't add any setter method. Declare all fields final and private. If a field is a mutable object create defensive copies of it for getter methods.
In object-oriented and functional programming, an immutable object (unchangeable object) is an object whose state cannot be modified after it is created. This is in contrast to a mutable object (changeable object), which can be modified after it is created.
An object is immutable if its state cannot change after construction. Immutable objects don't expose any way for other objects to modify their state; the object's fields are initialized only once inside the constructor and never change again.
The interesting question here is your question from the comments:
What kind of object would you have that you do not need to modify the values at some point? I'm guessing not a model class, correct? I've had to change the name of a person in my database - this wouldn't fit with this idea.
Well, consider things that are already immutable. Numbers are immutable. Once you have the number 12, it's 12. You can't change it. If you have a variable that contains 12, you can change the contents of the variable to 13, but you are changing the variable, not the number 12.
Same with strings. "abc" is "abc", and it never changes. If you have a variable that contains "abc", you can change it to "abcd", but that doesn't change "abc", that changes the variable.
What about a list? {12, "abc"} is the list that is 12 followed by "abc", and that list never changes. The list {12, "abcd"} is a different list.
And that's where things go off the rails. Because in C# you can do it either way. You can say that there is referential identity between those two lists if lists are allowed to mutate their contents without changing their identity.
You hit the nail right on the head when you talk about the "model". Are you modeling something that changes? If so, then it is possibly wise to model it with a type that changes. The benefit of that is that the characteristics of the model match the system being modeled. The down side is that it becomes very tricky to do something like a "rollback" functionality, where you "undo" a change.
That is, if you mutate {12, "abc"} to {12, "abcd"} and then want to roll back the mutation, how do you do it? If the list is immutable you just keep around both values and choose which one you want to be the "current" value. If the list is mutable then you have to have the undo logic keep around an "undo function" which knows how to undo the mutation.
As for your specific example, you certainly can create an immutable database. How do you change the name of someone in your immutable database? You don't. You create a new database that has the data you want in it. The trick with immutable types is to do so efficiently, without copying billions of bytes. Immutable data structure design requires finding clever ways to share state between two nearly-identical structures.
Declaring all fields readonly is a good step towards creating an immutable object, but this alone is not sufficient. This is because a readonly field can still be a reference to a mutable object.
In C# immutability is not enforced by the compiler. You just have to be careful.
This question has two aspects:
The first aspect demands sturcture like this:
public class MyClass
{
private readonly string _myString;
public string MyString
{
get
{
return _myString;
}
}
public MyClass(string myString)
{
// do some validation here
_myString = myString;
}
}
Now the problem - EF. EF requires parameterless constructor and EF must have setters on properties. I asked very similar question here.
Your type must look like:
public class MyClass
{
private string _myString;
public string MyString
{
get
{
return _myString;
}
private set
{
_myString = value;
}
}
public MyClass(string myString)
{
// do some validation here
_myString = myString;
}
// Not sure if you can change accessibility of constructor - I can try it later
public MyClass()
{}
}
You must also inform EF about private setter of MyString property - this is configured in properties of enitity in EDMX file. Obviously there will be no validation when EF will materialize objects from DB. Also you will not be able to use methods like ObjectContext.CreateObject (you will not be able to fill the object).
Entity Object T4 template and default code generation create factory method CreateMyClass instead of constructor with paremeters. POCO T4 template doesn't generate factory method.
I didn't try this with EF Code first.
Read this series by Eric Lippert https://docs.microsoft.com/en-us/archive/blogs/ericlippert/immutability-in-c-part-one-kinds-of-immutability.
An immutable value object is a value object that cannot be changed. You cannot modify its state, you have to create new ones
Check out Eric Lippert's blog:
Kinds of Immutability https://docs.microsoft.com/en-us/archive/blogs/ericlippert/immutability-in-c-part-one-kinds-of-immutability
Have a look at
Immutable object pattern in C# - what do you think?
How exactly would this work if you want to validate in the constructor of your Entity Framework generated model class?
It wouldn't work in this context because EF requires the properties of the entity class be public otherwise it can't instantiate it.
But you're welcome to use immutable objects further in your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With