Copying with y = x; does not cause any precision loss.
After the assignment, x == y is true.
Since x and y are equal, after
y = y + 1.4;
x = x + 1.4;
x == y is most likely true; however, as Eric Lippert pointed out (see comments below), this is not guaranteed.
Always compare doubles with a desired precision:
const double Eps = 1e-10;
if (Math.Abs(x - y) < Eps) {
// x and y are equal enough
} else {
// x and y are not equal
}
Of course, if you comment out only one of these, x and y will differ by approximately 1.4. They might differ by 1.399999999999999 or 1.400000000000001 or so. If both are very big (e.g. 1.0e25) the addition will have no effect, as it would affect decimals that are truncated. double has a precision of 15-16 digits. The same is true, if both are very small (e.g. 1.0e-25), because then their original values will be lost and the result will be 1.4.
In the C# Interactive window you can test that
> 1e+25 + 1.4 == 1e+25
true
and that
> 1e-25 + 1.4 == 1.4
true
... copied by value, as doubles are literals
Well, not quite. System.Double (C# alias double) is a value type. 3.141592654 is a double literal. In double x; the identifier x is a double variable (or field if it is declared at the type level).
But even if you copy ...
var p1 = new Person { Name = "John" }; // Where Person is a class.
var p2 = p1;
// Now, p1 and p2 reference the same object. I.e. they have the same value.
... the value of the variable is copied by value. The difference is that this value is a reference. The value is not a person object but a reference to it.
p2.Name = "Mark";
Now p1.Name == "Mark" is true, but the value of p1 did not change. It is still the same reference. The referenced object did change.
double d1 = 5;
double d2 = d1;
d2 = 77;
d1 is still 5. Because double is a value type, the variables contain the numbers directly. No references are involved.
In this other example the reference is passed by reference
var p1 = new Person{ Name = "John" };
AssignAnotherPerson(ref p1);
void AssignAnotherPerson(ref Person p)
{
p = new Person{ Name = "Sue" }; // Here p is an alias for p1.
}
After this method is called, p1 will contain the person Sue.
You can have four cases: (1) A value type passed by value. (2) A value type passed by reference. (3) A reference type passed by value. (4) A reference type passed by reference.