More new things in C#7 / Visual Studio 2017 (see yesterday on pattern matching). Remember C#7 isn't the same a .Net version upgrade - you can use these language features in projects targeting .net Core, .net 4.6, 4.5 and even 4.0 (and sometimes in v2/v3.5).
Normally a method can return only one value. It can return an int, or a string, or a custom class.
Creating a new class may be overkill just to return a few values. The classic example is TryParse, when you want a boolean result, and the parsed value if available. The framework solves this with the awkward "out" parameter.
if (int.TryParse(s, out i))
{
AddToTotal(i);
}
Since .net 4.0, we had Tuples as a "bucket" for returning simple values, but the "Item1"/"Item2" properties aren't very helpful.
var name = tuple.Item1;
var age = tuple.Item2;
If you're really desperate you can use dynamic types, with a performance hit.
C#7 provides two different improvements which help.
"out" paramters
In C#7 you no longer have to stick the variable declaration above the method call.
if (int.TryParse(s, out int i))
{
AddToTotal(i);
}
It's a small change, but probably the most useful one in C#7. This one works in .net 2.0 projects too.
TupleValue
There's a new package called System.ValueTuple which is required for this. It works for .net 4.0, 4.5 and later. Ignoring the language features, this is what it looks like if you were coding in VS2015.
{
var b = int.TryParse(s, out int i);
return new ValueTuple<bool, int>(b, i);
}
So this is a TryParse without the "out" parameter, and it looks a lot like the old Tuple.
if (result.Item1)
{
AddToTotal(result.Item2);
}
The magic happens because C#7 internalizes the System.ValueTuple, so what you write in VS2017 looks like this:
{
var b = int.TryParse(s, out int i);
return (b, i);
}
"ValueTuple" has disappeared, and we just see the types, within brackets. Now, you can name the return values.
{
var b = int.TryParse(s, out int i);
return (b, i);
}
Calling code can still use the obscure "Item1"/"Item2" names, but in VS2017 you can use the defined names.
if (result.IsOk)
{
AddToTotal(result.Value);
}
The calling code can also use the bracket syntax so the hidden tuple disappears completely.
if (isOk)
{
AddToTotal(value);
}
Or just use "var" around the whole result.
if (isOk)
{
AddToTotal(value);
}
All the awkward details of the underlying tuple are invisible, and the code is clean and readable.
Use with caution
Obviously if you're returning more than one value and you really don't want to return a class, check your design. "TryParse" or "TryLoad" methods are a good example where the pattern can make sense.