6

In C# 7 we can do like this:

byte.TryParse(p.Value, out _)

or like this

byte.TryParse(p.Value, out var _)

Are there any differences?

FaizanHussainRabbani
  • 3,256
  • 3
  • 26
  • 46
AsValeO
  • 2,859
  • 3
  • 27
  • 64
  • 3
    Yes there's a difference. Have you written the same piece of code using both, and actually got it to compile? – Ben Voigt Feb 15 '18 at 06:23
  • 2
    In first syntax you will have to declare `_` separately before calling this, in second syntax it will be declared as well. – FaizanHussainRabbani Feb 15 '18 at 06:29
  • @FaizanRabbani: It's not necessary to pre-initialize a variable used as an `out` parameter, although `ref` parameters do have to be definitely assigned prior to the call. – Ben Voigt Feb 15 '18 at 06:30
  • Seconds before I posted an answer.... [What's new in c# 7.0](https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/) covers it. – Zohar Peled Feb 15 '18 at 06:31
  • @BenVoigt thanks, correcting my comment, declare only. – FaizanHussainRabbani Feb 15 '18 at 06:31
  • 2
    @BenVoigt, I disagree that this one is a duplicate (at least not of the one that it's marked to be a dupe of), `_` are ommitted `out` parameters as of C# 7. – Paul Kertscher Feb 15 '18 at 06:34
  • 2
    @BenVoigt I don't see how duplicate answers this question. So, what's the difference here? – Evk Feb 15 '18 at 06:34
  • 2
    I agree with Paul. – Jaliya Udagedara Feb 15 '18 at 06:35
  • _ is for discards, this has a good answer, https://stackoverflow.com/questions/42920622/c7-underscore-star-in-out-variable – Jaliya Udagedara Feb 15 '18 at 06:35
  • @JaliyaUdagedara Yes, but this one is still different, since it explicitly asks about the difference between `out _` and `out var _` (spoiler: there is none) – Paul Kertscher Feb 15 '18 at 06:37
  • @JaliyaUdagedara Alright, it's covered in the accepted answer, but still: The scope of the question is different. – Paul Kertscher Feb 15 '18 at 06:38
  • @Enigmativity Sometimes `out` parameters are not needed. As of version 7, C# supports an `out` parameter that is a "throw-away" parameter, `_`. It will not (and cannot) be used. This is a good thing to tell your reader that the parameter is not used. – Paul Kertscher Feb 15 '18 at 06:51

2 Answers2

8

The difference is how they handle an existing variable named _.

string _;

int.TryParse("123", out var _); // legal syntax for discard
int.TryParse("123", out _); // compile error, string _ is incompatible with out int parameter

or

int _;

int.TryParse("123", out var _); // discard
Console.WriteLine(_); // error: variable is not assigned
int.TryParse("123", out _); // passes existing variable byref
Console.WriteLine(_); // ok: prints "123"

The reason for this is that out _ already had a meaning, and the language maintains backward compatibility with that old meaning. But out typename identifier is new syntax in C# 7, so there's no backward compatibility constraint.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
5

As opposed to what others in their comments said: No, there are no differences. They both produce the exact same IL.

Both

byte.TryParse(p.Value, out _);
Console.WriteLine(_);

and

byte.TryParse(p.Value, out var _);
Console.WriteLine(_);

will produce a compiler error with C#7, since _ is not intended to be used.

The usage of _ is not restricted to out parameters, but can be used for returns, too (as Evk pointed out)

byte.TryParse(p.Value, out var _); // I don't care about the out variable
_ = SomeMethod(); // I don't care about the return value

There is an excellent answer covering most things about ommitted parameters here.

Remarks: I would prefer out _ over out var _, since there is a clear syntactic distinction between out _ and out var legalVariableName.

EDIT

Obviously I'm not quite right here. There are some subtle differences, see Ben Voigts answer.

Paul Kertscher
  • 9,416
  • 5
  • 32
  • 57
  • 2
    `_ = SomeMethod()` is to explicitly express that you do not care about the result (and not acidentally forgot about it). It can be used anywhere (I mean just `void Main() { _ = 123;}` compiles fine without any `out _` and so on, so it's not related to the `out var _` block). – Evk Feb 15 '18 at 06:52
  • @Evk Thanks, edited my answer. – Paul Kertscher Feb 15 '18 at 06:57
  • 2
    `out var identifier` was legal in some prerelease versions, but not in C# 6. C# 7 is the first released version that permits out variables (which you called an inline declaration) was allowed. [Semi-official reference](https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/) – Ben Voigt Feb 15 '18 at 07:09
  • I think you have this backwards: *"With C#6 the former is illegal, but the latter is valid"* (former is first, latter is last) – Rufus L Feb 15 '18 at 07:22
  • 3
    This answer is incorrect on several levels. The lines of code are not equivalent, and the claims about C# 6 are faulty. – Ben Voigt Feb 15 '18 at 07:22
  • 3
    @Rufus: In C# 6 they're both invalid, the first because `_` is an undeclared identifier, the second because `out typename identifier` is illegal syntax. – Ben Voigt Feb 15 '18 at 07:23
  • @BenVoigt Well, yes, the variable has to be declared somewhere as `byte _;`. Just as whatever `p` is has to be declared. I thought that was assumed, but you have a point. – Rufus L Feb 15 '18 at 07:26