immutable value types - c#

I am reading Eric Liperts' blog about Mutating Readonly Structs and I see many references here in SO to this blog as an argument why value types must be immutable.
But still one thing is not clear, says that when you access value type you always get the copy of it and here is the example :
struct Mutable
{
private int x;
public int Mutate()
{
this.x = this.x + 1;
return this.x;
}
}
class Test
{
public readonly Mutable m = new Mutable();
static void Main(string[] args)
{
Test t = new Test();
System.Console.WriteLine(t.m.Mutate());
System.Console.WriteLine(t.m.Mutate());
System.Console.WriteLine(t.m.Mutate());
}
}
And the question is this why when I change the
public readonly Mutable m = new Mutable();
to
public Mutable m = new Mutable();
everything starts to work es expected.
Please can you explain more clear why Value Types must be immutable.
I know that it is good for thread safety, but in this case same can be applied to reference types.

Structs with mutating methods behave strangely in several situations.
The example you already discovered is a readonly field. A defensive copy is necessary because you don't want to mutate a readonly field.
But also when used as properties. Once again an implicit copy happens, and only the copy is mutated. Even if the property has a setter.
struct Mutable
{
private int x;
public int Mutate()
{
this.x = this.x + 1;
return this.x;
}
}
Mutable property{get;set;}
void Main()
{
property=new Mutable();
property.Mutate().Dump();//returns 1
property.Mutate().Dump();//returns 1 :(
}
This shows that mutating methods are problematic on structs. But it doesn't show that a mutable struct with either public fields or properties that have a setter is problematic.

The thread-safety is a clear technical reason. It applies to value types as well as to reference types (see System.String).
The more general guideline "value types should be immutable" is different. It is about readability of code, and comes mainly from the confusion that mutable values can cause. This code snippet is just one example. Most people would not expect the 1,1,1 outcome.

I don't know C# so I'll try to answer the 2nd part of your question.
Why value types must be immutable?
There are two types of objects from Domain Driven Design's point of view:
value objects/types - their identity is determined by their value (e.g. numbers: 2 is always 2 - an identity of number two is always the same, so 2 == 2 is always true)
entities (reference types) - they can consist of other value types and their identity is determined by their identity itself (e.g. people: even if there was man looking exactly like you, it wouldn't be you)
If value types were mutable, then imagine what could happen if it would be possible to change the value of the number two: 2 == 1 + 1 wouldn't be guarantied to be true.
See these links for more:
Value vs Entity objects (Domain Driven Design)
http://devlicio.us/blogs/casey/archive/2009/02/13/ddd-entities-and-value-objects.aspx

I think the tricky thing about that example is that one could argue it shouldn't be possible. You made an instance of Mutable read-only and yet you can change its value through the Mutate() function, therefore violating the concept of immutability, in a sense. Strictly speaking, however, it works because the private field x is not readonly. If you make one simple change in the mutable class then immutability will actually be enforced:
private readonly int x;
Then the Mutate() function will produce a compiler error.
The example shows clearly how copy-by-value works in the context of readonly variables. Whenever you call m you are creating a copy of the instance, as opposed to a copy of a reference to the instance -- the latter would occur if Mutable were a class instead of a struct.
Since everytime you call m you are calling 1) a copy of the instance, and 2) a copy of an instance that is read-only, the value of x is always going to be 0 at the time the copying takes place. When you call Mutate() on the copy it increments x to 1, which works because x itself is NOT readonly. But next time you call Mutate() you are still calling it on the original default value of 0. As he says in the article "m is immutable, but the copy is not". Every copy of the original instance will have x as 0 because the object being copied never changes whereas its copies can be changed.
Maybe that helps.

Related

modify a value-type variable in a using statement

In C#, if I have the following struct:
internal struct myStruct : IDisposable
{
public int x;
public void Dispose()
{
x = 0;
}
}
then do this in Main:
using (myStruct myStruct = new myStruct())
{
myStruct.x = 5;
}
it fails saying that myStruct is readonly. That makes sense as myStruct is a value-type.
Now if I add the folling function to the struct:
public void myfunc(int x)
{
this.x = x;
}
and change the Main code to this:
using (myStruct myStruct = new myStruct())
{
myStruct.myfunc(5);
Console.WriteLine(myStruct.x);
}
it works. Why ?
The short answer is "because the C# specification says so". Which, I admit, may be a bit unsatisfying. But that's how it is.
The motivation is, I'm sure, as commenter Blogbeard suggests: while it's practical to enforce read-only on the field access, it's not practical to do so from within a type. After all, the type itself has no way to know how a variable containing a value of that type was declared.
The key part of the C# specification (from the v5.0 spec) is here, on page 258 (in the section on the using statement):
Local variables declared in a resource-acquisition are read-only, and must include an initializer. A compile-time error occurs if the embedded statement attempts to modify these local variables (via assignment or the ++ and operators), take the address of them, or pass them as ref or out parameters.
Since in the case of a value type, the variable itself contains the value of the object rather than a reference to an object, modifying any field of the object via that variable is the same as modifying the variable, and is so a "modification via assignment", which is specifically prohibited by the specification.
This is exactly the same as if you had declared the value type variable as a field in another object, with the readonly modifier.
But note that this is a compile-time rule, enforced by the C# compiler, and that there's no way for the compiler to similarly enforce the rule for a value type that modifies itself.
I will point out that this is one of many excellent reasons that one should never ever implement a mutable value type. Mutable value types frequently wind up being able to be modified when you don't want them to be, while at the same time find themselves failing to be modified when you do want them to be (in completely different scenarios from this one).
If you treat a value type as something that is truly a value, i.e. a single value that is itself never changing, they work much better and find themselves in the middle of many fewer bugs. :)

Why are value objects immutable and copy-by-value?

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

Is it possible to access a reference of a struct from a List<T> to make changes?

I have a struct which I put in a List<T>, I want to edit some value in that struct at a specific position. Is this at all possible without making a copy of the struct, editing the copy, and replacing the entry in the List?
No, to be able to do it you need reference to element of inner array which is not provided by List/IList.
You can do that with unsafe code and arrays if you have to.
From J.Richter's "CLR via C#", 3rd edition:
Value types should be immutable: that is, they should not define any
members that modify any of the type’s instance fields. In fact, I
recommended that value types have their fields marked as readonly so
that the compiler will issue errors should you accidentally write a
method that attempts to modify a field.
...
Just keep in mind that value types and reference types have very
different behaviors depending on how they’re used.
Consider this code:
public interface IChangeStruct
{
int Value { get; }
void Change(int value);
}
public struct MyStruct : IChangeStruct
{
int value;
public MyStruct(int _value)
{
value = _value;
}
public int Value
{
get
{
return value;
}
}
public void Change(int value)
{
this.value = value;
}
}
and it's usage:
static void Main(string[] args)
{
MyStruct[] l = new MyStruct[]
{
new MyStruct(0)
};
Console.WriteLine(l[0].Value);
l[0].Change(10);
Console.WriteLine(l[0].Value);
Console.ReadLine();
}
The output is:
0
10
So it does what you need.
However the same won't work for List<T>. I guess by the reason, mentioned by Alexei Levenkov. So, I would strongly recommend you to change struct to class if the type in question is not immutable per instance.
Your best bet is probably to have your structures expose their fields directly, and then use code like:
var temp = myList[3];
temp.X += 4;
myList[3] = temp;
I consider the failure of .net to provide any means of updating list items in place to be a significant weakness in .net, but would still consider an exposed-field struct as being far superior to any alternative in cases where one wishes to represent a small group of orthogonal values which should not be "attached" to any other such group (such as the coordinates in a point, the origin and size of a rectangle, etc.) The notion that structs should be "immutable" has been repeated as mantra for a long time, but that doesn't mean it's good advice. Such notion stems largely from two things:
Structs which modify `this` in any members outside their constructors are quirky. Such quirks used to (and to some extent still do) apply to property setters, but not to structs which simply expose their fields directly. Because Microsoft wrapped all struct fields in properties, this meant that while mutable structures could have had sensible semantics if they'd had exposed fields, they ended up with quirky semantics; Microsoft then blamed the quirky semantics on the fact that structs were mutable, rather than on the needless wrapping of fields with properties.
Some people like to model .net has only having one kind of object, as opposed to having value types and reference types as distinct kinds of entities. The behavior of so-called "immutable" value types is close enough to that of reference types that they can pretend they're the same thing, whereas the behavior of easily-mutable value types is vastly different. In reality, it's easier to understand the behavior of exposed-field value types than to understand all the corner cases where so-called "immutable" value types behave differently from reference types, and understanding the latter is impossible without understanding the former. Note that while value types may pretend to be immutable, there is in reality no such thing as an immutable value type. The only distinction is between those which can be mutated conveniently and those which can only be mutated awkwardly.
In reality, if a type is supposed to represent a small group of orthogonal values, an exposed-field struct is a perfect fit. Even if one has to use clunky code like that shown above to update a field of an item in a List<structType>, it's better than any alternative using class types or so-called "immutable" structs. Knowing that myList is a structure with an exposed field X would be enough to completely understand the code above. The only remotely decent alternative if one were using a class or "immutable" struct would be myList[3] = myList[3].WithX(myList[3].X + 4);, but that would require that the type in question to offer a WithX method (and presumably a WithWhatever() method for each field). Such methods would increase many fold the amount of code one would have to read to find out for certain what a method would actually do (one might expect that WithX would return a new instance which was identical to the old one except for the value of X, but one wouldn't know until one read all the code involved; by contrast, knowing that X is an exposed field of the structure type would be sufficient to know what the above code would do.

In C# , Are Value types mutable or immutable ?

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

Why are C# number types immutable?

Why are ints and doubles immutable? What is the purpose of returning a new object each time you want to change the value?
The reason I ask is because I'm making a class: BoundedInt, which has a value and an upper and lower bound. So I was wondering: should I make this type immutable too? (Or should it be a struct?)
Firstly:
What is the purpose of returning a new object each time you want to change the value?
I think you might be mistaken about how value types work. This isn't some costly operation like you may be imagining; it's simply the overwriting of data (as opposed to, e.g., dynamic allocation of new memory).
Secondly: here's a very simple example of why numbers are immutable:
5.Increase(1);
Console.WriteLine(5); // What should happen here?
Granted, that is a contrived example. So let's consider a couple more involved ideas.
Mutable reference type
First, there's this one: what if Integer were a mutable reference type?
class Integer
{
public int Value;
}
Then we could have code like this:
class Something
{
public Integer Integer { get; set; }
}
And:
Integer x = new Integer { Value = 10 };
Something t1 = new Something();
t1.Integer = x;
Something t2 = new Something();
t2.Integer = t1.Integer;
t1.Integer.Value += 1;
Console.WriteLine(t2.Integer.Value); // Would output 11
This seems to defy intuition: that the line t2.Integer = t1.Integer would simply copy a value (actually, it does; but that "value" is in fact a reference) and thus that t2.Integer would remain independent of t1.Integer.
Mutable value type
This could be approached another way, of course, keeping Integer as a value type but maintaining its mutability:
struct Integer
{
public int Value;
// just for kicks
public static implicit operator Integer(int value)
{
return new Integer { Value = value };
}
}
But now let's say we do this:
Integer x = 10;
Something t = new Something();
t.Integer = x;
t.Integer.Value += 1; // This actually won't compile; but if it did,
// it would be modifying a copy of t.Integer, leaving
// the actual value at t.Integer unchanged.
Console.WriteLine(t.Integer.Value); // would still output 10
Basically, immutability of values is something that is highly intuitive. The opposite is highly unintuitive.
I guess that is subjective, though, in all fairness ;)
Integer variables are mutable. However, integer literals are constants, hence immutable.
int i = 0;
// Mutation coming!
i += 3;
// The following line will not compile.
3 += 7;
It's possible to make an integer field immutable, using readonly. Likewise, an integer property could be get-only.
As a mutable object, you have to lock an int variable before you change it (in any multi-threaded code that writes to your int from separate threads).
Why? Let's say you were incrementing an int, like this:
myInt++
Under the hood, this is a 32-bit number. Theoretically, on a 32 bit computer you could add 1 to it, and this operation might be atomic; that is, it would be accomplished in one step, because it would be accomplished in a CPU register. Unfortunately, it's not; there is more going on than this.
What if another thread mutated this number while it was in the middle of being incremented? Your number would get corrupted.
However, if you make a thread-safe copy of your object before you increment it, operate on your thread-safe copy, and return a new object when your increment is complete, you guarantee that your increment is thread safe; it cannot be affected by any operations on the original object that take place on other threads, because you're no longer working with the original object. In effect, you have made your object immutable.
This is the basic principle behind functional programming; by making objects immutable, and returning new objects from functions, you get thread safety for free.
It makes sense to have BoundedInt as a mutable type because it represents a variable that at any point in time has a specific value and that value can be changed but only within a certain range.
However integers themselves aren't variables so they should not be mutable.
Anything with value semantics should be immutable in C#.
Mutable classes can't have value semantics because you can't override the assignment operator.
MyClass o1=new MyClass();
MyClass o2=o1;
o1.Mutate();
//o2 got mutated too
//=> no value but reference semantics
Mutable structs are ugly because you can easily call a mutating method on a temporary variable. In particular properties return temporary variables.
MyStruct S1;
MyStruct S2{get;set;}
S1.Mutate(); //Changes S1
S2.Mutate();//Doesn't change S2
That's why I don't like that most Vector libraries use mutating methods like Normalize in their Vector struct.
I'm working on an academic project with Neural Networks. These networks do heavy computation with doubles. I run it on amazon cloud for days on 32 core servers. When profiling the application, the top performance problem is allocation of double!!
It would be fair to have a dedicated namespace with mutable types. "unsafe" keywords can be enforced for additional precaution.

Categories

Resources