Decimal is a typical type used in financial word, to prevent lost of information/precision during mathematical computations. There is one issue that is not put in a consideration. The
C# ECMA specification guarantees that the following types will be written atomically: reference types, bool, char, byte, sbyte, short, ushort, uint, int and float. There is no decimal on that list. It means that:
class AtomicityExample {
decimal _value;
void SetValue(decimal value) {_value = value;}
decimal GetValue() {return _value;}
}
If the code is executed by many threads, the returned value of GetValue method may be not a value that was set by a SetValue.
What is even less know is that the order of the operations in C# may change, due to .net optimization. Consider following code:
class OrderExample {
decimal d1;
volatile decimal d2;
decimal d3;
void Assign(){
d1 = 1;
d2 = 2;
d3 = 3;
}
}
The assignment in a code above can happen in following ways:
d1 = 1;
d2 = 2;
d3 = 3;
or
d1 = 1;
d3 = 3;
d2 = 2;
or
d3 = 3;
d1 = 1;
d2 = 2;
In other words volatile variable can be assigned only after d1 was assigned, but when exactly depends on a compiler. Be aware that majority of programmers don't even use volatile keyword, and without volatile keyword reads/writes of variables above can happen in any order. And it matters, because I've seen so many times a code that looked like:
class FalseSecurityExample {
decimal d1;
bool assigned;
void Assign(){
d1 = 1;
assigned = true;
}
decimal Calculate(){
if(assigned){
return d1;
}
}
}
It means that in an example above d1 may not be set before it is returned, and if you add to a consideration fact that decimal is not atomic, you can expect anything to be returned by this code.
When I ask people why do they write such code, and if they are aware of issues that are illustrated above, usually they answer, that we are not writing a project for NASA, or anything like that so bug off. Interesting.