Ok, this is a far stretched corner case we stumbled upon, but it made me curious.
Consider the following code:
public class Foo
{
private int foo;
public int Reset() => foo = 0; //remember, assignment expressions
//return something!
}
Will this code compile?
No, it won't if you have fail on all warnings; you'll get a member foo is assigned but never used
warning.
This code is, to all purposes, the same as:
public class Foo
{
private int foo;
public int Reset() { foo = 0; return foo; }
}
Which compiles just fine, so what is the problem here? Note that the =>
syntax is not the issue, its returning the assignment expression which seems to befuddle the compiler.
Boolean Variables and Data Type ( or lack thereof in C )Zero is used to represent false, and One is used to represent true. For interpretation, Zero is interpreted as false and anything non-zero is interpreted as true.
Initial implementations of the language C (1972) provided no Boolean type, and to this day Boolean values are commonly represented by integers ( int s) in C programs. The comparison operators ( > , == , etc.) are defined to return a signed integer ( int ) result, either 0 (for false) or 1 (for true).
The expressions true == 1 and false == 0 are both true. (And true == 2 is not true).
In the first example, foo
is assigned, but never read from. The 0
is assigned to foo
, then 0
is returned, regardless of what the value of foo
is (e.g. if another thread mutated it in the meantime).
In the second example, foo
is assigned, then read from. If another thread modified foo
in the meantime, the modified value will be returned, not 0
.
You can see this in action by comparing the compiled IL. Given the following code:
public class Foo
{
private int foo;
public int Reset() { return (foo = 0); }
public int Reset2() { foo = 0; return foo; }
}
The following IL is compiled for Reset
and Reset2
.
.method public hidebysig
instance int32 Reset () cil managed
{
.maxstack 3
.locals init (
[0] int32
)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: dup
IL_0003: stloc.0
IL_0004: stfld int32 Foo::foo
IL_0009: ldloc.0
IL_000a: ret
}
.method public hidebysig
instance int32 Reset2 () cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: stfld int32 Foo::foo
IL_0007: ldarg.0
IL_0008: ldfld int32 Foo::foo
IL_000d: ret
}
In Reset
, we only store to Foo::foo
(stfld
).
In Reset2
, you can see that we both store to it and load from it (stfld
+ ldfld
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With