Take the 2-minute tour ×

Value types are types which do not have an identity. When one variable is modified, other instances are not.

Using Javascript syntax as an example, here is how a value type works.

var foo = { a: 42 };
var bar = foo;
bar.a = 0;
// foo.a is still 42

Reference types are types which do have an identity. When one variable is modified, other instances are as well.

Here is how a reference type works.

var foo = { a: 42 };
var bar = foo;
bar.a = 0;
// foo.a is now 0

Note how the example uses mutatable objects to show the difference. If the objects were immutable, you couldn't do that, so that kind of testing for value/reference types doesn't work.

Is there any functional difference between immutable value types and immutable reference types? Is there any algorithm that can tell the difference between a reference type and a value type if they are immutable? Reflection is cheating.

I'm wondering this mostly out of curiosity.

share|improve this question

migrated from stackoverflow.com Jun 6 '12 at 20:18

This question came from our site for professional and enthusiast programmers.

4 Answers 4

up vote 2 down vote accepted

You are defining value types and reference in a language agnostic way, but doing so only by example in terms of changing of data members. Logically, making the types immutable makes you lose the only difference guaranteed by your definition (and the answer might be "no").

However, once we start looking at particular programming languages, then yes: there are more differences.

Consider the following C# example.

void increment()
    lock (synchro)

private int total = 0;
private SomeType synchro;

If SomeType is a reference type, this counter will be thread safe. If SomeType is a value type, then, due to boxing, each thread is locking a copy of synchro and increments may be lost under concurrency.

Of course, there are no genuine immutable types in .NET in the most abstract sense, as the monitors involved are implemented using hidden fields (akin to the C++ mutable keyword that can declare mutable members in otherwise immutable types). But on Stack Overflow, everyone will understand your question to refer to anything that their platform calls "immutable".

share|improve this answer
I'm not following what you are saying about locking synchro. Did you mean to lock (synchro)? –  Kendall Frey Jun 6 '12 at 19:47
Yes, I originally had @lock there but then inconsistently changed that as the @ would only puzzle non-C#-ists. Fixed. –  Jirka Hanika Jun 6 '12 at 19:58

Yes, equality still differs:

a: value type = 4;
b: value type = 4;

c: reference type = 4;
d: reference type = 4;

a == b; // true;
c == d; // false;

C# cheats for things like strings by consolodating references that are equivalent, but this isn't strictly necessary for immutable reference types.

share|improve this answer
You assume that equality is always defined as referential equality. This is not true- languages can have operator overloads that change this definition. –  DeadMG Jun 6 '12 at 20:30
@DeadMG: I'm assuming that any language that has reference types will provide some reference equality mechanism (even if the common equality is structural). I'm not aware of any counter-examples? –  Telastyn Jun 6 '12 at 20:32
What's the point of saying "They're referentially inequivalent" when the user of the type will not use referential equality to compare them? C# can do this and C++ can do it too. –  DeadMG Jun 6 '12 at 20:33
@Telastyn: Well, Haskell doesn’t provide any reference-equality mechanism because it would violate referential transparency. You can implement it using unsafePerformIO if you’re willing to rely on implementation-defined behaviour, though, so I dunno if it counts as a counterexample. –  Jon Purdy Jun 7 '12 at 3:20
The C# equality operator is icky. In vb.net, one may only use the = operator to compare things whose types provide explicit support for such comparison; if one wants referential equality, one must use the Is keyword. C# allows the == operator for any class-type rvalues, but its meaning may or may not match Object.Equals(). Consider what happens if one passes strings to public static bool IsEqual<T>(T obj1, T obj2) where T : class { return obj1 == obj2; }. What sort of comparison is used? –  supercat Jul 5 '12 at 19:40

Value vs reference type is not a language-agnostic term. A language such as C++ and C does not hold a distinction- it is an arbitrary imposition of some languages. However, I'm gonna try and roll with it anyway.

A simple example is sizeof(T). All reference types have the size of a pointer (possibly plus the size of another pointer, depending on what your memory management system is). Value types, however, do not. In addition, you can measure performance characteristics to determine whether you are dealing with a value or a reference type. In addition, it's not particularly safe to refer to value types in some contexts.

Reference types can do some things that immutable value types cannot- for example, references to them can rebound to another instance.

class X {
    const int imm;
    X() : imm(0) {}
class Y {
    const int* imm;
    Y() : imm(new int(0));
X x;
Y y;
y.imm = new int(5); // Whoops! The reference itself is not immutable.

Fundamentally, it must always be known whether a type is a value or a reference, else you cannot generate the correct code to access it.

share|improve this answer
I'm not referring to languages with value types and pointers, but reference types, where a type definition specifies which is the case. E.g. class vs struct. –  Kendall Frey Jun 6 '12 at 21:27
@KendallFrey: Which is exactly why I said that it's not at all language-agnostic. Of course, my fundamental point still holds. –  DeadMG Jun 7 '12 at 6:41
The question of whether a type is stored as a value or a reference is largely orthogonal to the question of whether it behaves like one. In languages or frameworks where variable assignment calls a user-defined copy constructor, things which are stored as heap references can behave like mutable value types, and in just about any framework which supports user-defined value types, things which to the compiler look like value types can behave like reference types. –  supercat Jul 5 '12 at 19:15
With regard to immutable types, a well-designed language and framework should allow immutable value types and immutable class types to be used interchangeably, but .net and C# have some limitations. For an immutable class type to really behave like an immutable value type, its class members must be callable directly, without using CallVirt (so properties invoked on a null reference could yield meaningful defaults rather than crashing), and it should be usable as a type argument to Nullable<T>. –  supercat Jul 5 '12 at 19:30


More: difference between a Value Type and a Reference Type

share|improve this answer
The infamous "value types are stored on the stack". :) I prefer to say they are stored "in place". –  Kendall Frey Aug 28 '13 at 13:22
This doesn't answer the question, because you can't determine where a variable is stored using code. –  Kendall Frey Aug 28 '13 at 13:24

Your Answer


