Variable X value
Values may be changeable or immutable, variables that contains values are always, by definition, mutable. Variable refers to something that varies, that changes, that is mutable.
It is common for those who write about the subject to use a looser language and not so academic, which can lead to a really wrong understanding. You are right in the doubt. It is rare who writes with all the details specified in the most correct way possible in these cases. And that’s what I did there in the question. That’s why this new question fits. So if someone says "variable x is immutable", read "the content of variable x is immutable".
Constants
Just as a constant, by definition, is immutable. I would like to say that the values of the constant are also always immutable. In C# they are, but some languages have managed to let a constant have the changeable value. It is a conceptual error that C# did not commit.
At least the C# makes it clear that PI
and the MaxValue
of the kind int
are constant. Whereas MaxThreads
and PercentualDeDesconto
sane readonly
, that is, they do not change during the entire execution of an application instance, but can change from one execution to another, or from one version to another. There are some other differences that are not the case now.
It is highly recommended that struct
s have their immutable values. This is in the C#documentation. It is very strange to have an object by value that is mutable. Technically it’s possible because can there is some situation that this is really useful and correct.
Class
es tend to be changeable. But they don’t have to be. The biggest example is string
which is a type by reference but which has semantics of value, that is, its value is immutable.
But how? I can change the value of a string
. I can do:
var s = "teste";
s = "mudei";
There was a change in the value of the variable and not the value of the string. You didn’t change the text, you created a new text and changed the reference (which is in the variable) to this new text.
Example of immutability
Look at this struct
:
struct Point {
public float X;
public float Y;
}
It is changeable. It should not. Why?
You can change the value of X and Y independently. You are changing the value itself and not the variable. And a struct
should not allow this.
It is not strange to change a part of the point without it being another point?
struct Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
It already changes everything. The only way to change a variable value is to completely change the value contained in it. In this case you create a new value and allocate it to the variable, you do not change the value allocated to it. Its use would be:
var p = new Point(2, 5);
// p.x = 7; seria um erro, você nem consegue acessar os membros individualmente.
p = new Point(7, 5);
Realized you can’t change just one member of the value? You have to create a new value and associate this new value with the variable. This is immutability.
You change not only the value, you change his identity. Cartesian point 2, 5 is different from point 7, 5, not the same point with a different characteristic.
Note adding public properties to access members x
and y
do not cause problems. But if you allow assigning values to them, you fall into the same problem as the previous example of Point
. Then you could create a property just with get
.
Example of mutability
Now look at this code:
struct Pessoa {
public string nome;
public int idade;
public Decimal salario;
public DateTime CadastradaEm;
}
public class Exemplo {
static void Main() {
Pessoa p;
p.nome = "João";
p.idade = 18;
Console.WriteLine("{0} tem {1} anos", p.nome, p.idade);
p.idade = 20;
Console.WriteLine("{0} tem {1} anos", p.nome, p.idade);
}
}
Another problem
Leaving aside that this is exposing fields for external direct access (it is just a simplified example, I do not need to follow such "good practices" here), what is the problem of this code?
If this is a struct
should be immutable but this is not the error. As it stands, it is clearly a mutable object, you can change members individually. No problem. That’s probably what you want in this case.
If this structure has several fields, it gets very large. Large objects do not look good in a struct
. After all struct
s are copied by value. Copies of large objects are inefficient. So we already have two reasons, inefficiency and mutability to say that this should be a class. The mistake was to define this structure as struct
instead class
. More details in this question.
Identity
In this example above despite changing the age of the person, the person is the same, the identity of the object is the same, so the object is mutable. Features of the object can be changed without the object becoming something else. Even if you changed the name from "John" to "Mary" (very common today :) ) it would still be the same person. A name can be exchanged for several factors, such as typo or change of marital status, just to name the most common.
When you use the code:
var i = 0;
i = 5;
Semantically is the same as saying:
var i = new Int32(0);
i = new Int32(5);
Int32
is the one struct
which equals to int
. Note that each value change, you are creating a new object, with equivalent identity. Actually it is being "stored" in the same place, it is replacing the previous value, but not only the variable has changed, but its value as a whole has changed.
So in the example:
int i = 0;
i++;
is the same as:
int i = default(Int32); //só para mostrar outra forma de interpretar a mesma coisa
i = new Int32(i + 1);
It doesn’t mean that the compiler interprets it exactly like this, but it’s a way that helps understand.
Note that the value of i
is being changed as a whole, according to the definition I gave above.
In C# 7 it is possible to use readonly struct
that favors the immutability.
In C# 9 it is easier to adopt it with the init
on the estates.
Completion
It seems strange at first glance, but if you look at the variable itself and its value as distinct things it is easy to understand that the value never changes, it is replaced by another.
The easiest way to understand immutability is to look at whether the change can occur in parts of the object (fields, properties, elements of a array, etc.) or may occur only in its entirety.
Immutability need not fit into any strict definition of object orientation. It is a concept applied to any paradigm.
The subject is very vast and is something that few understand correctly. I think I don’t understand everything correctly. But here’s an important part about it.
More information (the question is about Java, but the idea is the same).
Exercise
Answer if a phone that has the DDD (area code) and the number itself, can exchange your DDD and remain with the same identity? And he can switch operators and keep his identity?
If you create a variable (of type) int
with 0 and then assign 0 to it, it changed the identity?
Answers in the comment below
I put in the Github for future reference.
So the idea that an object of type
struct
represents a unique value that comes from this idea of immutability? That it makes no sense to alter attributes alone, but only to manipulate the object as a whole?– SomeDeveloper
@user1620696 I think I answered in the issue. but basically, yes. Answer and then I say if you got the "exercises" I left :)
– Maniero
An important observation (and "pedantic" almost): the Point struct, as defined (the version with private Fields), is not strictly immutable, although it is "effectively immutable". This detail can have significant implications for multi-threading codes (ie, completely wrong code although apparently correct vs correct code). Otherwise, very good answer! Details: http://stackoverflow.com/questions/16678416/different-between-immutable-immutable-and-effectively-immutable-objects
– Bruno Reis
@Brunoreis quite relevant for a more complete understanding yes. I wanted to simplify and focus on what was most important to the issue.
– Maniero
Answering the questions, it seems to me that changing the DDD really changes the identity of the phone. Already changing the carrier does not change the identity. And finally the
int
will change the identity yes, taking into account the way I understood that the compiler understands assignments to types value.– SomeDeveloper
@user1620696 About the phone is just that. In real life it’s like this, in the model, it should also be. The case of the
int
It’s more complicated. Some say you change your identity, some say you don’t. In fact its logic is correct, by coincidence the value is the same, but the identity is different. But some people say that if you can’t have anything that differentiates the identity is the same. That makes sense too. So unless someone gives me a clear reference to that, I leave both as true. Even because in this case only has use theoretically. No phone has a practical change.– Maniero
This idea of one value being exchanged for another instead of being changed is clearer now.
– Diego Farias