19

Value types behavior shows that whatever value we are holding cannot be changed through some other variable .

But I still have a confusion in my mind about what i mentioned in the title of this post . Can anyone clarify?

Kuntady Nithesh
  • 11,371
  • 20
  • 63
  • 86

3 Answers3

27

Value types can be either mutable or (modulo some weird edge cases) immutable, depending on how you write them.

Mutable:

public struct MutableValueType
{
    public int MyInt { get; set; }
}

Immutable:

public struct ImmutableValueType
{
    private readonly int myInt;
    public ImmutableValueType(int i) { this.myInt = i; }

    public int MyInt { get { return this.myInt; } }
}

The built-in value types (int, double and the like) are immutable, but you can very easily create your own mutable structs.

One piece of advice: don't. Mutable value types are a bad idea, and should be avoided. For example, what does this code do:

SomeType t = new SomeType();
t.X = 5;

SomeType u = t;
t.X = 10;

Console.WriteLine(u.X);

It depends. If SomeType is a value type, it prints 5, which is a pretty confusing result.

See this question for more info on why you should avoid mutable value types.

Community
  • 1
  • 1
dlev
  • 48,024
  • 5
  • 125
  • 132
  • Just two observations - in the *mutable* case, the field could (and probably should) still be behind a property. In the *immutable* case, the field could be explicitly `readonly`. – Marc Gravell Aug 17 '11 at 06:14
  • @Marc Good points. I actually considered going back and making the `readonly` edit; suppose I'll make both now. Thanks. – dlev Aug 17 '11 at 06:15
  • 1
    @dlev, so when you have something like the following. int i = 5; i = 5+2; The 5+2 is passed to a new int and the referenced returned to i? IMHO when SomeType prints 5 I'm not confused, it's when SomeType prints 10 that boggles me. Good answer btw. – Jethro Aug 17 '11 at 06:16
  • @Jethro You're conflating variables with their contents a bit. `i` is a variable, which contains the integer 5. When you say `i = 5 + 2`, you put a new integer (7) into the memory held by `i`. What you *don't* do is change the integer 5 into the integer 7. And thanks for the compliment :) – dlev Aug 17 '11 at 06:18
  • 1
    @dlev, but by changing the memory held by i are we not changing the value of i making it mutable. I've always known Strings as being immutable, hence when you do someting like this str = str + "change"; you are in fact calling the String.Concat which creates a new block of memory and then points str to that block of memory. Is this what is happening with i or does the Integers original memory block get changed? Hope that makes sense. – Jethro Aug 17 '11 at 06:29
  • @Jethro `i` itself is definitely mutable; it's a variable, and it can vary. The `Int32` struct that it stored, though, is not mutated. It is replaced wholesale by a new one. The problem with value types is that they don't "own" their storage. `i`'s memory and the memory used for 5 *are the same*. So while assigning a new int to `i` does replace that memory, it's still not considered to be mutating the struct. – dlev Aug 17 '11 at 06:34
  • @dlev, thanks for the mini lesson, really cleared up some of my understandings. Thanks again. – Jethro Aug 17 '11 at 06:38
  • 2
    In your example, if SomeType is a value type with an integer field X, u.X will be 5. That information and the code above are sufficient to show that information; it should hardly be "unexpected". Now suppose t were a class type, and *anyplace* between the creation of t and the WriteLine call--even before the "t.x=10", there was a call to SomeInheritableClassObject.SomeVirtualFunction(t). Without examining *all possible overrides of SomeVirtualFunction*, there's no way to know what the WriteLine would output. I'd regard the predictable behavior of mutable structs to be far preferable. – supercat Oct 06 '11 at 19:45
  • @MarcGravell: Why should a mutable struct field be hidden behind a property? If a struct has a public field `X`, a C compiler won't have to guess at whether `SomeReadOnlyStructure.X += 4;` should be legal, or whether `someReadOnlyVariable = SomeReadOnlyStructure.X` needs to make a copy of the structure because the `X` getter might modify it. Properties on structures are fine when they make sense, but if the implementation of the property can't change without breaking things, what is gained by using a property rather than a field? – supercat Aug 26 '12 at 16:55
  • I have my doubt about your example of "inmutable", seems that is not inmutable, as MSDN says: **when a property getter returns a value type, the caller receives a copy. Because the copy is created implicitly, developers might not be aware that they are mutating the copy, and not the original value. Also, some languages (dynamic languages, in particular) have problems using mutable value types because even local variables, when dereferenced, cause a copy to be made.** https://msdn.microsoft.com/en-us/library/ms229031%28v=vs.110%29.aspx – ElektroStudios Nov 02 '15 at 16:22
  • I don't think this is a convincing example - why would ever right code like this? I mean: you present this as an example why mutable value types are bad, but the reference-typed variable case is at least as bad - when you read `u.X` and try to figure out what that might be, you might see that `u` is initialized with `X=5` and never modified, and might easily draw the wrong conclusion that `u.X` is 5 too. By mixing aliasing and mutation, you now need to play the (impossible) game of following all those aliases... and good luck if `SomeType` plays similar tricks internally... – Eamon Nerbonne May 06 '16 at 13:36
3

all primitive value types like int, double,float are immutable.But structs by itself are mutable.so you have to take measures to make them as immutable as it can create lot of confusions.

Ashley John
  • 2,379
  • 2
  • 21
  • 36
  • Ok , But wat about reference types ? while reading through documents i came to know that they can be either mutable or immutable . how is that ? – Kuntady Nithesh Aug 17 '11 at 04:55
  • @Nitesh . That also depends upon how you implement it .The System.Text.StringBuilder class is an example of a mutable reference type. It contains members that can change the value of an instance of the class. An example of an immutable reference type is the System.String class. After it has been instantiated, its value can never change – Ashley John Aug 17 '11 at 05:00
1

Any value-type instance which holds any information can be mutated by code which can write the storage location wherein it are contained, and no value type-instance can be mutated by code which cannot write the storage location wherein it is contained. These characteristics make privately-held storage locations of mutable value types ideal data containers in many scenarios, since they combine the updating convenience that stems from mutability, with the control that would come from immutability. Note that it is possible to write the code for a value type in such a way that it's impossible to mutate an existing instance without first having an instance (perhaps a newly created temporary instance) which contains the desired data, and overwriting the contents of the former instance with the contents of the latter, but that won't make the value type any more or less mutable than it would have been absent such ability. In many cases, it merely serves to make mutation awkward and to make it look as though a statement like:

  MyKeyValuePair =
    new KeyValuePair<long,long>(MyKeyValuePair.Key+1, MyKeyValuePair.Value+1>;

will create a new instance but leave the existing instance unaffected. If KeyValuePair were an immutable class, and one thread was performing a MyKeyValuePair.ToString() while another thread was executing the above code, the ToString call would act upon either the old or new instance, and would thus yield either both old values or both new values. Because KeyValuePair is a struct, however, the above statement will create a new instance, but it won't make MyKeyValuePair refer to the new instance--it will merely use the new instance as a template whose fields will be copied to MyKeyValuePair. If KeyValuePair were a mutable struct, the most natural expression of the likely-intended meaning for the above code would be more like:

  MyKeyValuePair.Key += 1;
  MyKeyValuePair.Value += 1;

or perhaps:

  var temp = MyKeyValuePair;
  MyKeyValuePair.Key = temp.Key+1;
  MyKeyValuePair.Value = temp.Value+1;

and the threading implications would be much clearer.

supercat
  • 77,689
  • 9
  • 166
  • 211