Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

c#-7.0

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?

like image 691
Wojtek322 Avatar asked Oct 13 '20 08:10

Wojtek322


People also ask

What is the difference between assignment and discard in Java?

The discard clarifies your intent: the result of the assignment isn't needed or used. The following example uses a standalone discard to ignore the Task object returned by an asynchronous operation. Assigning the task has the effect of suppressing the exception that the operation throws as it is about to complete.

Why is my _ variable not assigned a value?

This error is because _ isn't assigned a value, and may not even be assigned a storage location. If it were an actual variable, you couldn't discard more than one value, as the previous example did. Discards are useful in working with tuples when your application code uses some tuple elements but ignores others.

What happens when you use a discard variable in an expression?

A discard variable used here will not change the fact that it is an unused expression, rather it will appear to the compiler, to you, and others reviewing your code that it was intentionally unused. Thanks for contributing an answer to Stack Overflow!

Why do we need to discard a variable in Python?

They enhance its readability and maintainability. You indicate that a variable is a discard by assigning it the underscore ( _) as its name. For example, the following method call returns a tuple in which the first and second values are discards. area is a previously declared variable set to the third component returned by GetCityInformation:


2 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.

like image 177
Zohar Peled Avatar answered Oct 11 '22 13:10

Zohar Peled


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.

like image 22
Liam Avatar answered Oct 11 '22 13:10

Liam