What is the difference between discard and not assigning a variable?

Viewed 656

In c# 7.0, you can use discards. What is the difference between using a discard and simply not assigning a variable?

public List<string> DoSomething(List<string> aList)
{ 
//does something and return the same list
}
_ = DoSomething(myList);
DoSomething(myList);

Is there any difference?

3 Answers

There's absolutely no difference between the two code lines.
Both of them translate to exactly the same IL:

public void A(List<string> myList)
{
    _ = DoSomething(myList);
}

public void B(List<string> myList)
{
    DoSomething(myList);
}

Both translate to:

IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call instance class [System.Private.CoreLib]System.Collections.Generic.List`1<string> C::DoSomething(class [System.Private.CoreLib]System.Collections.Generic.List`1<string>)
IL_0007: pop
IL_0008: ret

You can see it yourself on SharpLab
(Note: I can't actually read IL, but this is the result of both A and B methods)

Discards are useful, as Liam wrote in his answer, for out parameters you're not going to use, for tuple deconstructions, for pattern matching, and for switch expressions.
You can read all about it in the official documentation.

Update following Liam's comment: Please note that I'm only referring to this specific scenario.
When used as intended, discards are memory-efficient and/or improve the readability of your code.

Discards are more for out parameters that you don't care about. For example:

if (int.TryParse(123, out _))
{
   ....
}

They really only exist to prevent you having to declare a variable that you don't use. So the old way of doing above would be to do:

int throwAway;
if (int.TryParse(123, out throwAway))
{
   ....
}

To quote the docs:

Because there is only a single discard variable, and that variable may not even be allocated storage, discards can reduce memory allocations. Because they make the intent of your code clear, they enhance its readability and maintainability.

So discards are memory-efficient (though this depends on usage) (don't do this as an optimisation; IMO this very much falls into the area of premature optimisation, as the efficiency gain is tiny) but more importantly they make your code more readable by making it obvious that you don't intend to do anything with the variable.

Following two lines don't have a difference at compile level.

_ = foo();
foo();

Subtle difference in IDE level: foo(); can show a warning in Visual Studio later than 2019, because you didn't use return value of a function.

According to MSDN,

discards can reduce memory allocations. Because they make the intent of your code clear, they enhance its readability and maintainability.

Reference: https://docs.microsoft.com/en-us/dotnet/csharp/discards

Following link might also help.

it seems that the discards have a higher sinergy with other paradigms introduced in the most recent versions of C# like tuples deconstruction.

Reference: Discard feature significance in C# 7.0?

Related