Discard of return values and out parameters in C# 7

C# 7 allows to discard return values and out parameters. The underscore character is used as wildcard for these not required values.

The following source code shows an example of a function call where the caller wants to ignore the return value. Of course, in this case an assignment is not needed at all but it is possible by using the wildcard character.

static void Main(string[] args)
{
  DoSomething();
  _ = DoSomething();
}

private static int DoSomething()
{
  return 1;
}

Let’s stop for a moment and think about the example. This easy example may raise some questions:

  • Which of both syntax styles should be preferred?
  • Do we have any disadvantages if we use the short syntax?
  • Is it fine to ignore a return value at all or should we always assign and analyze return values?

If you read source code which contains the short syntax “DoSomething()” for a function call with ignored return value you will miss a very important fact: the function has a return value! Ignoring the return value may lead to errors. So, this code is a source of errors and the error is hidden as the reader of the code must explicitly have a look at the interface to see whether the function has a return value.

The syntax with the discard character explicitly contains the information that the function has a return value which is ignored. Of course, there is still an open question: why do we ignore the return? And as usual we should explain the “why” within a comment in the source code.

So, the second syntax is a little bit longer but it provides important information. The first syntax instead hides information and is a source for errors. It would be nice to get a compiler warning in such cases.

Discard ternary operator result

Let’s look at a second example where the compiler actually prevents ignoring of returns, the ternary operator. If you try to use the ternary operator without assignment of the return value, you will get a compiler error.

static void Main(string[] args)
{
  bool x = true;

  int y = (x == true) ? DoSomething() : DoSomethingOther(); //OK

  (x == true) ? DoSomething() : DoSomethingOther(); // compiler error

  _ = (x == true) ? DoSomething() : DoSomethingOther();   // OK
}

private static int DoSomething()
{
  return 1;
}

private static int DoSomethingOther()
{
  return 2;
}

Of course, the new discard wildcard can be used in this case too. But again, if we read such source code, we should ask why the return is ignored.

Discard out parameter

Beside the return value a function may have out parameters. As out parameters are nothing else as additional returns we can use the wildcard character for these parameters too.

static void Main(string[] args)
{
  DoSomething(out int _);
}

private static void DoSomething(out int x)
{
  x = 1;
}

Discard tuple elements

If the return value of a function is a tuple, we could discard the whole return value or parts of the tuple.

static void Main(string[] args)
{
  _ = DoSomething();
  (int result, _) = DoSomething();
}

private static (int result, int errorCode) DoSomething()
{
  return (5, 0);
}

Summary

It is possible to ignore return values or out parameter by using the discard parameter. But in my opinion, this is bad coding style. Ignoring these values means either the interface is strange as it contains unnecessary elements or the user of the interface mistakenly ignores important elements. Therefore, the discard parameter should be used in exceptional cases only and a clarifying comment is mandatory which explains why the interface element can be ignored.

Werbung
Dieser Beitrag wurde unter .NET, C# veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit deinem WordPress.com-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s