dalle
dalle

Reputation: 18507

Using a variable as an out argument at point of declaration

When reading a comment to an answer I saw the following construct to declare and initialize a variable:

int variable = int.TryParse(stringValue, out variable) ? variable : 0;

Is this allowed, correct and well defined in C#? What happens under the hood? Is the following what happens?

  1. Is variable first initialized to zero?
  2. then passed to int.TryParse (which assigns a value)?
  3. then optionally read (if int.TryParse return true)?
  4. and then, once again assigned/initialized?

Upvotes: 15

Views: 747

Answers (4)

chrisl08
chrisl08

Reputation: 1658

I haven't opened Visual Studio to try this, but yes, this is allowed.

It all depends on the "stringValue" variable. If that is parsable to an integer, int.TryParse will return true, and [variable] will have an integer value. If not, then variable will be set to 0.

Does this make for readable code? Apparently not.

Upvotes: 2

D J
D J

Reputation: 7028

Yes you are right for execution. You can also look into MSIL generated here

C# Code

 string stringValue = "5";
 int variable = int.TryParse(stringValue, out variable) ? variable : 0;

MSIL generated

1.  IL_0000:  nop    
2.  IL_0001:  ldstr      "5" // load string
3.  IL_0006:  stloc.0
4.  IL_0007:  ldloc.0
5.  IL_0008:  ldloca.s   variable
6.  IL_000a:  call       bool [mscorlib]System.Int32::TryParse(string, int32&)
7.  IL_000f:  brtrue.s   IL_0014
8.  IL_0011:  ldc.i4.0
9.  IL_0012:  br.s       IL_0015
10. IL_0014:  ldloc.1
11. IL_0015:  stloc.1
12. IL_0016:  ret

Which clarifies what it does behind the scene.

Statement 5 is allocating the variable onto stack. Statement 6 is calling the method. Statement 7,8,9 are actually exeuting the bool expression.

Upvotes: 10

user1131435
user1131435

Reputation:

int variable declares variable, and out variable necessarily initializes it. Both of these things must happen before variable is used anywhere, and because of the out declaration, this holds true.

As pointed out by Lasse V. Carlsen, from TryParse's documentation, TryParse will by default assign it the value of 0 if the conversion fails:

When this method returns, [return] contains the 32-bit signed integer value equivalent of the number contained in s, if the conversion succeeded, or zero if the conversion failed. (emph. mine)

If you expand the ternary function out, you'd see:

int variable;
if (int.TryParse(stringValue, out variable))
    variable = variable;
else
    variable = 0;

which is, in and of itself, a legal expression. The two paths are:

  • TryParse assigns the value to variable and returns true, leading to an assignment of variable to itself
  • TryParse initializes variable to 0 and returns false, leading to the assignment of variable as zero by the ternary condition

This isn't particularly clear code, though, and I wouldn't recommend doing it.

Upvotes: 5

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391336

This is a trick that happens to work because it is simply a rewriting of an ordinary if-statement. This code is equivalent to this:

int variable;
if (int.TryParse(stringVariable, out variable))
    variable = variable;
else
    variable = 0;

The sequence is as follows:

int.TryParse is called, variable is not initialized before this but it doesn't have to either. An out parameter does not require a definite assigned variable. As part of the method execution, the variable will be given a value, and int.TryParse will return true or false.

If the method returns true then the result of the expression will be variable and thus we will execute basically variable = variable.

If the method returns false then the result of the expression will instead be 0, and variable will now be given the value 0 regardless of what it was given as part of int.TryParse. In this case, however, this will not change the variable because int.TryParse has already given the variable a default value when it returns false which also happens to be 0.

This is basically a way to get everything onto one line.

Personally I would've written this code like this:

int variable;
int.TryParse(stringValue, out variable);

Upvotes: 8

Related Questions