0

According to Wikipedia's article on value objects, C# value objects are both immutable and copied attribute-wise.

If they're immutable, why make copies? Even if it helps memory locality, is that general enough of an optimization to make it the default behavior?

Edit: Oh, I think I misunderstood immutability.

So does immutability mean you can't modify the attributes individually, but you can replace the entire internals from an existing object? But doesn't that violate "if two things are equal, they will always be equal"?

leewz
  • 3,201
  • 1
  • 18
  • 38
  • 1
    I think that article is just badly worded. It's trying to say the opposite of what it appears to say. – David Schwartz Aug 07 '14 at 21:40
  • 1
    Value types do not have to be immutable. It is recommended but not necessary. `System.Drawing.Rectangle` is not immutable. – clcto Aug 07 '14 at 21:46
  • 1
    @DavidSchwartz That article is terrible; among other things is includes the usual "struct is kept in the stack while classes are stored in the heap" nonsense. – Michael Edenfield Aug 07 '14 at 22:03

3 Answers3

0

So does immutability mean you can't modify the attributes individually, but you can replace the entire internals from an existing object?

Yes.

But doesn't that violate "if two things are equal, they will always be equal"?

No. Why would it? If you replace the internals from an existing object, you get a new object with different internals.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Given that value objects are supposed to be threadsafe: if we both have access to the same value object, and you can replace its internals without me knowing, I would definitely not call that "a new object". – leewz Aug 08 '14 at 01:31
  • But it is a new object. Each time I replace an internal, I get a new object with a different internal. If you have an immutable object and you modify it, you get a new immutable object with the modification. That is the semantic of immutable objects. – David Schwartz Aug 08 '14 at 03:04
  • At a different address? – leewz Aug 15 '14 at 00:13
  • @leewangzhong Yes, and no. The reference is at the same address, but it's a reference to a different "referenced object", at a new address. – David Schwartz Aug 21 '14 at 03:11
0

I'm not agreeing with the given claims, but I'll attempt to explain what I believe they intend to say.

The fact that structure types are immutable means that

public struct S { int i; }
public S f() { /* omitted */ }
public void g() { f().i = 3; }

is a compile-time error: it wouldn't make sense to modify f()'s result, because the modification would be immediately lost.

In contrast,

public struct S { int i; }
public S f() { /* omitted */ }
public void g() { var s = f(); s.i = 3; }

is fine, but s.i = 3; can be interpreted as rewriting all of s: it can be interpreted as equivalent to (pseudo-code) s = { 3 };, where { 3 } constructs a whole new S value object.

But doesn't that violate "if two things are equal, they will always be equal"?

By their interpretation, this is still true. After s.i = 3;, s is a whole new value. Before the assignment to s.i, s was equal to f()'s result. After the assignment to s.i, s itself fundamentally changes, and it's not just a modification of a property of that object, you've got a whole new object, which was never equal to any other object except perhaps by chance.

Their interpretation is consistent with how C# actually works, although their phrasing is not how I usually see it, or how I would put it. Beware that other documentation may make different claims that at first glance will seem to totally contradict these.

0

Everything is copied by value unless you use the ref keyword. The difference between value types and reference types is:

  • variables/fields whose type is a value-type are allocated where they are declared. This can be the current stack frame if they are local method variables. But it can also be the heap if they are part of an object already on the heap.
  • variables/fields whose type is a reference-type contain a reference to an object that is allocated on the heap.

Since value-types are allocated "in-place" when you assign a variable to another, your're actually copying the object's members. When you assign a reference-type variable to another you're copying the reference to the same object on the heap. Either way, you're always copying the content of the variable.

lgoncalves
  • 2,040
  • 1
  • 14
  • 12