C# 7 is available on new Visual Studio 2017 and comes with some new features. I wouldn’t call them ‘revolutionary’ features, but they add on the language very well and some of them can be very helpful. Personally, I have anticipated some features since C# 6 version.
TLDR; Sample code can be found here.
C# 7 comes with new features that I really like and I strongly believe they will be very useful in daily coding life, while others I think won’t help me anytime soon.
Look at C# Language Design on GitHub or the proposals made from the community for the language, to get an idea of the new language features and the features to come.
Before I begin, I wish to share my experience with VS 2017, C# 7, .NET Standard/Core.
I used Visual Studio 2017 Community version to experiment with new syntax (I don’t have yet a license for Pro, sniff). I also wanted to experiment on code by writing some unit tests (this is my way to learn new stuff, I first write a unit test and then fiddle around with code, aiming to make it pass), so I used xUnit (which I am not a big fan of, but anyways). Both projects were .NET Standard 1.4 projects, but then I realized that this doesn’t work, as you can see on my SO post. So, the answer was to make the test project a runnable application, I used .NET Core 1.1 but with no luck, so what I did in the end, was to create a new test project, targeting .NET Framework 4.6.2. Project with samples remained to .NET Standard.
Also, do not forget to use the System.Runtime Nuget package. Take a look on samples at Github (link is available above).
Man, I love this. It is the first topic to discuss because I anticipated this for a long time. Personally, I really, really hated the old way, where you needed to declare a variable before calling the method with the output parameter. I was feeling funny everytime I was forced to code stuff like this:
I strongly believe that this is not elegant and I was really disappointed when they decided to not include this on C# 6 release.
But, here it is. Now you can declare the variable and the out parameter on the same line
Yeah, I know, this isn’t exactly a revolution or an outstanding feature, but it is helpful and increases readability (of course, you need to get your eyes used to this new syntax, as you might lose a variable declaration while reading). Please note also that you can declare it as a
var, instead of a specific type.
As it is expected, you can declare more than one output parameters (duh!) and use this new syntax. The cool thing with this though, is that you can decide which output parameter you wish and which you don’t. Cool stuff!
Bear with me, I know, the following example is a bit dull, but it demonstrates the use of discards (which can be declared with an underscore)
As you can see, you omit the parameter you don’t wish to return using out _. How cool is the third example? You discard the first and the last and you get the middle one. Nice!
There is one gotcha though and this has to do with scoping. The scope rule is strict, having the variables accessible only in the scope body they are declared in.
That said, the following code will not work, you will get a compiler error, stating that the name ‘[name]’ does not belong to current context.
but the following will work just fine
Tuples and deconstruction
Please note, in order to use the new tuples, you need to download a Nuget package, as it is not yet on core language code. So, that said, download the
System.ValueTuple 4.3.0(or higher)
Forget the old, rusty, rigid syntax for tuples, now you just declare them by type and you have them.
Look on the following example, the
GetPerson method returns a Tuple with two strings and an integer.
The syntax is pretty much simple. For declaration, you wrap in parenthesis the tuple items with their types and optionally names for them, if you want to make the signature more readable.
In order to create a tuple instance, you wrap your objects in parenthesis, of course matching the declaration, like in the example above, first define the two strings, then the integer value.
You consume it in a similar fashion. Of course, you can consume a simple tuple object and access each item individually like this:
But this is not sexy, okay? What about this?
That’s what I’m talking about! You can wrap your tuple elements in parenthesis, declare them and they are ready to be used like normal variables. Of course, you can declare them as
var as well or even better, for shorthand syntax (see deconstruction below):
Declaring them all as vars.
Also, like out variables, tuples have discards as well, so you can omit elements you don’t wish to use, just like at the following example.
Finally, on tuples, there is another interesting feature, called deconstruction. We looked at that feature on the previous examples, with the sexy syntax.
But you can use it on classes as well, making them to behave like a tuple. You just need to declare a method called
Deconstruct in your class, which can receive a number of output parameters, which will be deconstructed.
In the code above, I want to deconstruct a
Person object to strings
lastName and integer
age. So, I use the
Deconstruct method, declaring three output parameters, matching the description I gave earlier. I just give them the values from the public properties of the class, which were populated on instantiation.
Person can be deconstructed like this:
Although pattern matching is a hot feature for the language, I won’t spend much time discussing that.
I would say that pattern matching is not that really useful to the language, it was a feature ‘nice to have’ mostly, by reading the patterns.md proposal, at least that is my take.
You can think of it as the
Is operator in steroids. That operator is extended to test an expression against a pattern, and in this case we have various types of patterns.
We can match an expression based on type or constant value or null and other discussed here.
This feature is very useful in some coding scenarios. Mostly, I like it because it gives me better syntax in an is-a situation or in testing a nullable type. Seriously, I like it only for that.
Check on the following example (of course the following can shorten significantly by using a ternary operator, but for the sake of the example I am more explicit)
CustomReferenceType method, I check if the object passed is of type
CustomReferenceType and I create a new variable
t of that type from the object (same as using the
as operator and assigning the result to a new variable). Same goes for the
IsNullableIntGreaterThanTen method, in which I check if the nullable integer value passed is not null, create a new variable
v, assing the integer value there and return Boolean result based on its value.
In essence, I avoid doing this:
Another coding scenario that pattern matching is useful and is demonstrated by almost everyone, is when using a switch-case statement. Now, you can match a case block by a pattern, which can be a type or a constant expression or null.
Be careful though, the patterns are not matched in an ordered fashion, as the compiler can match patterns out of order, as it is optimized to reuse the results of an already matched pattern in order to compute the result of matching of other patterns.
Also, note that the
default case will execute last, regardless of the order you specify it on code.
Other features that I like are the local functions. I think this is a good addition and improves readability.
When reading on code, as a human being, I read from top to bottom and jumping to references while reading, meaning I will jump to the next function declared. I prefer to write a private function immediately after its call, so a reader can jump to it directly, without much effort searching in the class.
With local functions, you literally have the chance to write it just after your call in the caller’s body. All the caller’s scoped variables are available within the local function, which helps you to define more readable signatures, with less parameters (the more the parameters a method has, the dirtier it is).
Of course, this is one advantage that it gives you, the other is scoping, the only one that has access to this method is the caller and only that. This can help you create more meaningful inner functions, closer to the caller’s context.
Be careful though, not to overdo it, as this can lead to some insanely huge looking parent methods, which is the worst thing you can do with your code. As a rule of thumb, use local functions only when you know they will be short, else use other private methods and try to separate concerns, do not make methods more 10-20 lines long.
- 1-10 lines is perfect
- 10-20, you need a short check on code
- 20-30, it’s getting out of hand
- 50-60+, Houston, we have a problem
If your method does not fit your screen, then you are in some deep trouble. And don’t cheat with pivot screens.
Expression bodied members
Finally, this is another great feature. I loved expression bodied members in the previous release, my single line methods looked so good with that syntax.
With the new syntax, constructors, destructors, even getters and setters can have expression bodies.
Look on the previous example, the constructor has an expression body.
You can throw an exception when using the ternary conditional operator (
?:), the null coalescing operator (
??) or as the body of an expression-bodied lamda or method.
Take a look at the following examples:
Cool new features, improving your experience with the language.
I haven’t been through many other features, maybe the most notorious of them, the pattern matching. This is on purpose. As I said in the beginning, my intention was to go through stuff that I find useful in my daily routine, and for the moment, I do not find pattern matching that useful for me. Probably I need to dig deeper and see the advantages, but for the moment I do not use it.
What new features do you use? Do they come in handy for you?
If you liked this blog post, please like, share and subscribe! For more, follow me on Twitter @giorgosdyrra.