In this article, we are going to learn about the differences between a discard variable and the usual variables in C#. We will also see some practical uses of a discard. 

To download the source code for this article, you can visit our GitHub repository.

C# 7 introduced discards as placeholders for values we do not have any use for in our code. They are write-only variables that allow us to explicitly inform the compiler or anyone reading our code to discard their content. They are particularly useful in scenarios where we receive a value but have no intention of using it.

How a Discard Variable Differs From a Usual Variable

A discard is represented by the underscore (_) character:

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

_ = "This is the syntax for a discard";

Discards are like unassigned variables. But unlike normal variables, we cannot declare discards with var or any type keyword.

We can have more than one discard within a scope. We use each underscore placeholder to discard a single value. Even though it looks like discards have values, when we attempt to retrieve any of them, we get a compiler error: CS0103: The name '_' doesn't exist in the current context. 

We should note that declaring an underscore with a var or other types makes it a regular variable and loses its discard functionality:

string _ = "This is no longer a discard";

Why Do We Use a Discard Variable?

If we ignore the discards, why do we need them?

Discards help us maintain a clean codebase with minimized warnings. When we call a method with a return value we do not care for, assigning that value to a discard takes care of compiler warnings about unused variables. Some APIs and libraries also return unwanted values. We employ discards to manage them and still conform to the API/library signatures.

When working with pattern matching and deconstruction, discards allow us to ignore parts of a data structure that are irrelevant to us. 

They are a feature that contributes to simplifying our codes and improving clarity.

Use Cases for Using a Discard Variable in C#

Using a discard in our code effectively communicates our intention to the compiler and other code readers. It signifies that we deliberately intend to disregard the outcome of an expression.

We could ignore the result of an expression, one or more elements within a tuple expression, an out parameter in a method or the target of a pattern-matching expression.

Let’s explore various scenarios where discards come in handy.

Discards as Out Parameters

We can discard the value of an out parameter when calling any method that uses one. 

For example, a TryParse() returns a bool. If the parse is successful, it returns true and saves the value of the parsed argument to the out parameter:

public static (bool result, string errorMessage) GetNumber(string input)
{
    bool result = int.TryParse(input, out _);

    if (!result)
    {
        return (false, "Not a valid number");
    }

    return (true, "");
}

In our example, we use int.TryParse() to attempt to parse an input, which is a string by default. We use discard for the out parameter to indicate that we are not interested in the parsed integer value. We are only checking if the parse was successful or not. 

Discards in Tuple Deconstruction

When working with tuples, we often do not require all the values they contain. So, let’s start with a simple method:

public static (int, int, int) GetSum(int num1, int num2)
{
    return (num1, num2, num1 + num2);
}

The GetSum() method returns a three-tuple containing the numbers to be added and the resulting sum. 

Using a discard, we can selectively ignore the specific tuple elements we want and use actual identifiers for the values we care about:

var (_, _, sum) = DiscardExamples.GetSum(9, 89);

Since the two numbers are already passed into GetSum() when we call it, we do not need their values returned. Our interest is obtaining the sum, so we designate the other two numbers as discards.

Discards in Pattern Matching

Given an array of items containing various data types, we can use pattern matching within a switch expression to identify the type of each item:

public static void GetType(object[] objects)
{
    foreach (var item in objects)
    {
        Console.WriteLine(item switch
        {
            string => "it's a string",
            int => "it's an int",
            _ => "Neither string nor int"
        });  
    }
}

Our method checks if the items in our array are a string or an integer.  We treat any other data type as a discard, so the method will print Neither string nor int to the console.

Discards in Lambda Expressions

From C# 9, we can use discards to represent two or more unused input parameters of a lambda expression:

Func<char, char, char> constant = (_, _) => 'C';

To maintain compatibility for lambda expressions written in older versions of C#, when a single input parameter is assigned the _ identifier, it is interpreted as a valid read/write variable in newer versions.

Conclusion

Using the discard _ in our code conveys to the compiler that we mean to disregard the outcome of an expression deliberately. It proves especially handy in situations where we receive a value but have no plans to utilize it.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!