Author avatar

Dániel Szabó

Out Parameters and Discards in C#

Dániel Szabó

  • Feb 15, 2020
  • 6 Min read
  • 325 Views
  • Feb 15, 2020
  • 6 Min read
  • 325 Views
Languages Frameworks and Tools
C#

Introduction

In this guide, we will take a close look at two features introduced in C# 7.0. These features essentially changed how developers worked and applications were developed. The out parameter comes in handy when methods need to return more than one values. This parameter is passed by reference, and basically transforms the formal parameter into an alias for the argument which must be a variable. This is very similar to the ref keyword, but the main difference is the latter needs to be initialized beforehand. Discards are basically temporary variables or dummy variables that are not used in application code. The main purpose of discards is to provide a reusable variable, which decreases the memory allocation and improves readability and maintainability.

Out Parameter

Before C# 7.0, there was an older version of the out keyword. We are going to focus on the improved one introduced in the new version.

Rules:

  1. out parameter can be passed without devclaration and initialization.
  2. out parameter can use var type in the method parameter list.
  3. You don't have to have the same name for the out parameter in the function definition and call.

We are going to focus on a small app that calculates whether we met the SLA for a given customer. We will take two arguments. One is called totalHours and the other is called availableHours.

The version without out parameters looks something like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;

namespace Pluralsight
{
    public class OuterDiscards
    {
       
        public static void Main()
        {
            Console.WriteLine("Please enter the totalHours: ");
            double totalHours = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine("Please enter the availableHours: ");
            double availableHours = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine(SLA(totalHours, availableHours));
            Console.ReadKey();
        }
        public static string SLA(double a, double b) {
            double result = Math.Round(((b / a) * 100), 2);
            string sla = $"Total hours: {a}, Available hours: {b} => SLA:{result} %";
            return sla;
        }

    }
}
csharp

The following output is produced when the code is executed.

1
2
3
4
5
Please enter the totalHours:
1000
Please enter the availableHours:
999
Total hours: 1000, Available hours: 999 => SLA:99.9 %
bash

Utilizing the fact that out variables can be passed without declaration or initialization, we can modify the code as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;

namespace Pluralsight
{
    public class OuterDiscards
    {
       
        public static void Main()
        {
            Console.WriteLine("Please enter the totalHours: ");
            double totalHours = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine("Please enter the availableHours: ");
            double availableHours = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine(SLA(totalHours, availableHours, out double result, out string sla));
            Console.ReadKey();
        }
        public static string SLA(double a, double b, out double result, out string sla) {
            result = Math.Round(((b / a) * 100), 2);
            sla = $"Total hours: {a}, Available hours: {b} => SLA:{result} %";
            return sla;
        }

    }
}
csharp

Note how the function call and the definition were extended with the out double result, out string sla. This technique is called in-line declaration of the out parameter. The method is required to assign a value to the out parameters before returning. They are also allowed to be overloaded based on the out parameters. Async and Iterator methods don't have an out parameter.

If we wanted, we could have used Implicit type declaration for our out variables as well as the var type, which has the same scope in the local method body as the out parameter. So we could modify the function call and declaration this way: out double result, out string sla. The type of var is dynamically identified upon assignment.

Discards

Discard variables use the underscore symbol: _.

The simplest discard example imaginable looks like this. It is called deconstruction.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;

namespace Pluralsight
{
    public class OuterDiscards
    {
       
        public static void Main()
        {
            var tuple = (1,2,3,4,5,6,7,8);
            (_, var first, _, var second, _,_,_,_ ) = tuple;

            Console.WriteLine($"first: {first}, second: {second}");
            
            Console.ReadKey();
        }        
    }
}
csharp

Our task was to create a variable called first and another called second from the first and third indexes of the tuple.

Executing the script gives us the following output.

1
first: 2, second: 4
bash

The real power of discards lies with the combination of out variables.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;

namespace Pluralsight
{
    public class OuterDiscards
    {
        public static void prs(string dtstr)
        {
            if (DateTime.TryParse(dtstr, out _))
            {
                Console.WriteLine("Date is valid");
            }
            else
            {
                Console.WriteLine("Date is not valid");
            }
        }
        public static void Main()
        {
            prs("02/29/2019");
            Console.ReadKey();
        }                
    }
}
csharp

In this example, we created a function that takes a string as an argument and tries to parse it against the DateTime object. The reason we use out _ as second argument is that we do not want to record the outputl we only care if the specified string can be parsed as a DateTime object.

Conclusion

In this guide, we explored two new features that have been added to C# with version 7.0. These small apps demonstrated how you can utilize them and make your code easier to maintain and more flexible. I hope this guide has been informative to you and I would like to thank you for reading it.

5