28

When coding resharper recommends that if you're to discard or ignore the return of a method, that you use this syntax:

_ = TheMethodICouldCareLessAboutTheReturnValue();

I know you could just call it without assignment to _ just the same, so why does the _ as an assignment matter?

4
  • 8
    Is very helpful for calls like TheMethodICouldCareLessAboutTheReturnValue(out _) or (x, _, _) = TheMethodICouldCareLessAboutTheReturnValue
    – John Wu
    Commented Oct 28, 2021 at 14:24
  • 32
    @JohnWu TheMethodICouldntCareLessAboutTheReturnValue* ;)
    – Alexander
    Commented Oct 29, 2021 at 0:18
  • 3
    @Alexander: Things I don't care about get named things like asdasd, aaa, aaaa, and so on. TheMethodICouldCareLessAboutTheReturnValue implies some epsilon of caring, so the name is not entirely wrong. Maybe TheMethodICouldBarelyCareLessAboutTheReturnValue?
    – Flater
    Commented Oct 29, 2021 at 8:22
  • 1
    "my epsilon on the scale of caring is usually zero" can be a useful thing to say outside of software engineering, too. Commented Oct 29, 2021 at 18:01

5 Answers 5

45

It matters for two reasons. One is conventional, the other technical.

The conventional reason is that _ conveys active disinterest in the returned value. Sure, you could write var dontcare instead, but that's just a different arbitrary value.

But as you pointed out, you could also omit the assignment, so it's not just about choosing the shortest name possible. This brings us to the technical reason.

There are cases where you have to declare a parameter and you cannot simply omit it. This applies to out parameters in method calls, and named tuples when you don't care about all of the tuple's members.

// Out params

if (DateTime.TryParse(dateString, out _))
    Console.WriteLine("dateString can be parsed as a DateTime");

// Tuples

var (minimum, _) = FindMinMax(myData);
Console.WriteLine($"The minimum value is {minimum}");

There may be other use cases, these are the two I can think of because I encountered them before.

Is this necessary? Well, it's an easy way to suppress warnings about unused variables. Not all developers care about warnings, but those who do would be pestered by these useless warnings for cases where they are knowingly not using a variable that the compiler forced them to declare anyway.

9
  • (Also see my comment on Thomas's answer about repeated use of _ being magic) Commented Oct 28, 2021 at 15:07
  • 1
    Is it possible that the discard variable can save memory because since the value is going to be discarded, no memory needs to be allocated
    – CPlus
    Commented Oct 28, 2021 at 17:45
  • 9
    @user16217248 1) If the variable isn't used, the compiler can optimize it away anyway. 2) 8 bytes almost certainly isn't going to make a blind bit of difference to your program anyway. 3) Profile before you optimize. Commented Oct 28, 2021 at 17:50
  • 6
    (Warning: I'm nitpicking over semantics) I wouldn't say that using _ is "an easy way to suppress warnings about unused variables" - strictly speaking, to suppress a warning you use #pragma warning disable 01234 - whereas using a discard _ isn't "suppressing" a warning, it's about positively expressing your intent to ignore an unimportant or inconsequential result. The term "suppress" has connotations of basically sweeping issues under a rug (and invites future investigation during your next refactoring), whereas using discard is the opposite and implies finality and confidence.
    – Dai
    Commented Oct 28, 2021 at 22:53
  • With tuples like (x,_)=expr you can almost say "we copied the tuple syntax from Python, so why not copy their successful style as well?". Commented Oct 29, 2021 at 3:51
33

By using the discard _, you are making it explicit that you, as the developer, understand that the method is returning a value but that you do not care about the value. This gives some insight into the code for reviews or future developers.

If you don't explicitly capture the return value, it is ambiguous as to your intention. Did you not realize that the method returns values? If you didn't realize that the method returned a value, does that also mean that you are missing a check against that return value against expectations? Or was it intentional and the return value doesn't mean anything in your context? These would be questions going through the mind of other developers that can easily be avoided with a very small change.

6
  • 2
    _ is slightly more than a standard variable name in that you can use it multiple times without error; var (_, _, foo) = bar; is valid while var (baz, baz, foo) = bar; is not. Commented Oct 28, 2021 at 15:06
  • 1
    @PhilipKendall Hm. I see the confusion. I mean "standard" in "a standard way of saying we are discarding this variable". The allowed reuse is a technical detail. You could prefix a variable with "discard" and end up with var (discard1, discard2, foo), but there's no good reason to do that in a language like C# that lets you reuse the special _ name. Let me think on this wording a little bit.
    – Thomas Owens
    Commented Oct 28, 2021 at 15:12
  • @ThomasOwens , just call it a discard, rather than a variable as that is what it is.
    – David Arno
    Commented Oct 28, 2021 at 17:07
  • @PhilipKendall Unless you're using an earlier version of C# where _ is treated as a normal identifier and must be unique in a given lexical scope. Also, while you can have multiple separate _ discards inside a method, you cannot (unfortunately) have more than 1 discarded method parameter (which can happen when you're implementing an interface or using awkward out params).
    – Dai
    Commented Oct 28, 2021 at 22:57
  • 1
    @Dai have you got an example of cannot .. have more than 1 discarded method parameter ?
    – Caius Jard
    Commented Oct 29, 2021 at 15:53
14

Other answers have focussed on why the language includes the _ token, but I'd like to focus on why ReSharper is recommending it.

I think you are putting the emphasis on the wrong part of the message: ReSharper isn't asking you to add the _, it's asking you to check whether the return value is important.

As the answer by Thomas Owens puts it:

If you didn't realize that the method returned a value, does that also mean that you are missing a check against that return value against expectations?

The tool is saying "Hey! This function returns a value! Maybe it's important!" If that return value is an error code, failing to handle it could lead to a serious bug - and one which you won't notice until the error condition comes up.

The suggestion to discard it with _ is a side-effect of that check: it's a way of answering the tool with a "Thanks for pointing it out, I've had a look, and in this case it's not important." It's making use of the language syntax so that you don't have to write an ugly "ignore check" comment next to the line.

2
  • This was my first thought. I've always found the diagnostic messages for these sorts of issues somewhat misleading. It's not a syntax issue, it's a warning that you might be committing one of the classic blunders.
    – bta
    Commented Oct 29, 2021 at 21:48
  • 1
    So the compiler is combining two things: 1) "warning: unused return value", 2) "but I, the compiler still, think there's a 90% chance you actually want to ignore it so here's a quick way to turn off the warning I just gave you -- I have no opinion on whether it's good or bad style". Commented Oct 30, 2021 at 22:49
-2

I think it's simply a natural bias in C# editors towards suggesting newer features. I think that as discard (the underscore) was added in C#7.0, editor maintainers looked for possible new suggestions, saw _=exprWithIgnorableReturn(); as a possible use, and added that hint. I don't think there was any deeper thought process than that.

My reasoning is, as has been noted, we've long been able to use var dontCare=exprWithIgnorableReturn(), but choose not to. C# editor extensions could have had "uncaught possibly unneeded return value, consider using a dummy?", but again, choose not to. The purpose of an ignoreable return value is that it can be ignored, as in completely ignored. Adding code to say "I realize this has a return value but choose to ignore it" is almost always clutter.

7
  • "The purpose of an ignoreable return value is that it can be ignored" - is there some way of marking a return value as "ignorable"? Because if not this statement is meaningless, because all return values are ignorable as far as the language is concerned, but ignoring some is definitely a bug.
    – IMSoP
    Commented Oct 30, 2021 at 9:26
  • @IMSoP The premise of the question is that there are actual useful functions where an ignorable return value is understood. They're run for the side-effect or to modify ref parameters, with a "maybe someone will want to see this" return value. You might ask the OP to give an example. Or a sample: stackoverflow.com/questions/2735701/… Commented Oct 30, 2021 at 22:01
  • I didn't say the functions don't exist, I asked if there was a way of marking those functions, or recognising them on sight, other than using the discard syntax. I also notice that at least two of the answers to the question you linked are discussing how to mark the value as ignored, either with comments, or with the equivalent in other languages of the _= syntax.
    – IMSoP
    Commented Oct 30, 2021 at 22:14
  • @IMSoP I still feel as if the premise of the Q includes: 1) somehow a coder knows they want to ignore a return value (how is outside the scope of the Q) and 2) normally we don't mark that -- we call it like a non-value returning function. Number 2 is what my last line, about clutter, refers to. Igoring error values is a special case, which we clearly would comment. But I'm not sure how this line of questioning relates to what I wrote in the "answer" part. Commented Oct 30, 2021 at 22:39
  • 1
    I disagree that it's clutter, but I also disagree with the premise of your answer that ReSharper is suggesting it just because it can. Some people don't think it's clutter, and do use comments and dummy variables to mark it in other languages; it's those people that the tool is trying to be helpful to.
    – IMSoP
    Commented Oct 31, 2021 at 23:40
-5

Something else also to consider is that you also make it clear to the compiler that you do not care about this value.

3
  • 6
    Can you elaborate on how this helps the compiler to accomplish what goal? Perhaps with an example where not doing this results in suboptimal bytecode?
    – Philipp
    Commented Oct 29, 2021 at 8:17
  • 1
    But doesn't not capturing the return value, at all, make it equally clear to the compiler? It seems _=expr; only makes it more clear to us humans. Commented Oct 29, 2021 at 22:10
  • 1
    Speaking as a human, it doesn't make it clearer to me either. It seems like a useless feature that compels the programmer to clutter his code with garbage.
    – trollkotze
    Commented Oct 31, 2021 at 18:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.