Friday Links 0.0.24 - C#-7: Out Variables and Local Functions
This is based on an email I send my .NET team at work
Happy Friday,
Over the next few weeks I’m going to be taking a look at some of the new features in C#-7, that just became available with the recent release of Visual Studio 2017.
Out Variables
I’m sure you’ve used a lot of the .NET’s Try*
functions, like int.TryParse
.
These functions return a bool
indicating if the method succeeded, and then returning
the real result as an out
parameter.
They’re kind of clunky to use because you have to declare the variable before hand:
int page;
if (int.TryParse(Request.QueryString["page"], out page))
{
// do something with the page
}
With this new feature, you can move the declaration to inside of the method call:
if (int.TryParse(Request.QueryString["page"], out int page))
{
// do something with the page
}
You can also now use var
instead of the type delcaration
You can also ignore the out variable. For example, if I cared that a string was
parseable to an int
but didn’t care what the actual value was.
public static bool IsIntString(string s)
{
return int.TryParse(s, out _);
}
Notice there is no type declaration. The variable has to be _
or else its a
compile error.
What’s also funny is that Resharper (2016.3.2) thinks the above is an error, though it compiles just fine.
The new feature is syntactic sugar for the old version, and doesn’t change the semantics of the code.
Here was the initial proposal for the feature: https://github.com/dotnet/roslyn/issues/6183
What’s interesting is that initially they wanted to change the scope of the out
variable: it would only be accessible inside of the if
block. It looks like
that design was dropped somewhere along the way.
I really like this feature and it will help clean up a lot of clunky Try* code.
Local Functions
You can now declare functions inside of other functions. This is meant for utility functions that are only really helpful in one place. You’ll never need to call it from elsewhere.
public static int LocalFunctionTest()
{
return GetInteger();
int GetInteger()
{
return 10;
}
}
You could have used local lambdas like Action<T>
in earlier versions of C#, but
lambdas don’t let you use out and ref variables.
Local functions can also helpfully reference local variables through closures:
public static void LocalFunctionTestWithClosure()
{
string s = "hi";
Console.WriteLine(ConcatWorld());
string ConcatWorld()
{
// s comes from enclosing scope
return s + " world";
}
}
I think there are a few scenarios where this feature could be pretty useful, but I’d be wary of over use. You probably shouldn’t find yourself using more than a couple local functions in a given method. I think I’m still inclined to use a regular utility function unless I had good reason to turn it into a local.
I need a little more experience with this feature to determine how I like it.
Here’s the original proposal: https://github.com/dotnet/roslyn/issues/259