1

This subject has been discussed many times and is clear: Is relying on && short-circuiting safe in .NET?

What I cannot find is a clear answer if the short circuit is also reliable when out parameter is used in the right part of the if clause:

int foo;
....
if ( false == Int32.TryParse( bar, out foo ) || 0 == foo )

When I try this code then it works. But I am just a bit worried if the behavior is reliable, because I don't know how the compiler is translating the code and accessing foo.

My question:

Is the access to foo really done after the TryParse which would consider any changed value or the compiler can sometimes read the value before TryParse [because of some optimizations] and therefore I cannot rely on this code.

Peter VARGA
  • 4,780
  • 3
  • 39
  • 75
  • Unless there's a bug on the C# compiler, it will work, if there were a possibility of the variable being accessed before being assigned then the compiler would complain about it. – Gusman May 11 '18 at 21:46
  • 1
    @Steve The 2nd condition is very necessary **when** it could be successfully parsed. – Peter VARGA May 11 '18 at 21:52

2 Answers2

3

Is the access to foo really done after the TryParse which would consider any changed value

Yes, this will be the case.

or the compiler can sometimes read the value before TryParse [because of some optimizations] and therefore I cannot rely on this code.

No, it will not read foo before the call to Int32.TryParse; one being that the logical OR will always evaluate the left side and only evaluates the right side if it's necessary. two, it will not evaluate the right side first because the foo variable is not initialised at that point which would cause a compilation error (assuming it's a local variable).

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
2

You can verify this works by using the new language features in C#:

if (!int.TryParse("0", out int foo) || foo == 0)
{
    //foo == 0 or the tryparse failed
    //foo still exists here though, so if it fails, it will still == 0
}

You can see that the declaration of foo happens inside the int.TryParse call, which wouldn't happen if foo == 0 was evaluated first. This is legal syntax in C# 7 and up. Really this is all syntactic sugar for this:

int foo = 0   
if (!int.TryParse("0", out foo) || foo == 0)
{
    //foo == 0 or the tryparse failed
}
Ron Beyer
  • 11,003
  • 1
  • 19
  • 37
  • I like this explanation but unfortunately I am stick to an old C# version due to the used framework. – Peter VARGA May 11 '18 at 21:56
  • @AlBundy The framework version and the language version are independent, you can use C# 7.1 and compile against .NET 2.0 if you want. – Ron Beyer May 11 '18 at 21:59
  • :-) - I am developing for [NinjaTrader 7](https://ninjatrader.com/support/forum/showpost.php?p=404820&postcount=2) and I have to use the C# compiler they provide :-(( – Peter VARGA May 11 '18 at 22:00