roslyn: Proposal: Allow using discard for throwaway variables

Related to https://github.com/dotnet/roslyn/issues/20#issuecomment-70366000 and #8049.

Practical use cases:

http://nsubstitute.github.io/help/received-calls (Checking calls to properties)

https://confluence.jetbrains.com/display/ReSharper/Return+value+of+pure+method+is+not+used

Before:

var mode = calculator.Mode;
calculator.Mode = "TEST";

//Check received call to property getter. We need to assign the result to a variable to keep the compiler happy: "Only assignment, call, increment, decrement, and new object expressions can be used as a statement".
var temp1 = calculator.Received().Mode;
var temp2 = calculator.Received().Mode;
var temp3 = calculator.Received().Mode;

After:

var mode = calculator.Mode;
calculator.Mode = "TEST";

//Check received call to property getter
var * = calculator.Received().Mode;
var * = calculator.Received().Mode;
var * = calculator.Received().Mode;

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 41 (8 by maintainers)

Most upvoted comments

@jcouv Thank you!

@alrz

Whilst C# does indeed allow the following:

F();

where F is non-void, writing the above code leads to problems. Did I write that because I’m not interested in the return value, or because I didn’t realise there was one? In the latter case, the fact that I don’t handle it could be a sign of a bug. Good practice suggests therefore that I should make my intentions explicit (as, unsurprisingly, F# enforces) by being able to write:

var _ = F();

Now it’s obvious that I’m just disinterested in the return. Due to the beauty of the Roslyn analyzers, I can also enforce this rule, without requiring a breaking change to the compiler.

A further use of this syntax can be seen in my own Succinc<T> project (which provides a means of implementing pattern matching, options and other other union types and the like in the existing C# language). I make extensive use of _ as a throw-away variable. In some cases, this is through necessity, such as when testing properties. Taking an example from UnionT1T2Tests.cs:

[Test]
public void AccessingCase2ForUnionWithT1_GivesMeaningfulException()
{
    var union = new Union<int, string>(2);
    try
    {
        var _ = union.Case2;
        Fail("Expected exception to be thrown");
    }
    catch (InvalidCaseException e)
    {
        AreEqual($"Cannot access union case {Variant.Case2} when case {Variant.Case1} is selected one.",
            e.Message);
    }
}

Here the line var _ = union.Case2; has to contain a throw-away variable as I’m assessing a property and the C# compiler mandates that a read of a property must be assigned to a variable. I then suffer the problem that eg ReSharper, or potentially other analyzers, complain that I’m not using _. If C# 7 supported * as a genuine “I don’t care about this value, but I must assign a result somewhere” variable, then this would both enable us that want to explicitly indicate in code we don’t care about the return and analyzers to be happy.

So I’d contend you are wrong: var * = ... makes complete sense.