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.


4 Answers 4


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".

  • I'm not following what you are saying about locking synchro. Did you mean to lock (synchro)?
    – Kendall Frey
    Jun 6, 2012 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, 2012 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.

  • 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, 2012 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, 2012 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, 2012 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, 2012 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, 2012 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.

  • 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. Jun 6, 2012 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, 2012 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, 2012 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, 2012 at 19:30

In brief: A Value Type holds the data within its own memory allocation and a Reference Type contains a pointer to another memory location that holds the real data. Reference Type variables are stored in the heap while Value Type variables are stored in the stack.

More: difference between a Value Type and a Reference Type

  • The infamous "value types are stored on the stack". :) I prefer to say they are stored "in place". Aug 28, 2013 at 13:22
  • This doesn't answer the question, because you can't determine where a variable is stored using code. Aug 28, 2013 at 13:24
  • While this is true in some cases, this is a compiler/runtime design choice (the infamous "implementation defined") rather than having anything to do with mutability, reference type and value types
    – awdz9nld
    Oct 17, 2016 at 14:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.