There are two separate concepts at work here. The first is that DateTime
is a value type (a.k.a. a struct) while Person
is [presumably] a reference type (a class). Because of this, when you do:
DateTime date1 = DateTime.Now;
DateTime date2 = date1;
date2
will result in copying the value, so the two variables will not reference the same object.
With classes, when you do:
Person p1 = new Person();
Person p2 = p1;
p1
doesn't actually contain a Person
, it just contains a reference to a person. That reference is then copied (by value) to p2
. The effect of copying that reference is that both variables are now "pointing to" or "referencing" the same object.
Next there is the issue of mutability. Person
, in this case, is a mutable type. That means that it can be changed. An immutble type on the other hand cannot be changed once constructed.
The line:
p2.Age = 2;
is actually changing the object that p2
references, and since p2
and p1
both reference the same object, p1.Age
would be 2
after that line of code.
Now, for demonstration purposes, let's make an immutable Person
class:
public class Person
{
private int _age;
public Person(int someAge)
{
_age = someAge;
}
public int Age
{
get { return _age; }
}
public Person Grow()
{
return new Person(_age + 1);
}
}
If we do something like this:
Person p1 = new Person(1);
Person p2 = p1;
p2 = p2.Grow();
the second line is doing just what it was before, ensuring that both point to the same object, but the third line is different. Rather than changing (or mutating) that person to make it a year older, our Grow
method returns a new Person
object that represents someone a year older. After doing this p2
and p1
will no longer be referencing the same object; I have just changed what object p2
references to a new one that the Grow
method just created.
This second example is rather similar to what's going on with DateTime
. You can't mutate a DateTime
object; it is immutable. Calling it's methods (in this case the plus and minus operators) returns and entirely new object. By convention, value types shouldn't be mutable without some compelling reason, as it can often be tricky to deal with them. Reference types can be either immutable or mutable; neither has significant problems (in the general case).