Visual Studio 2017 and C# 7 were officially released earlier this year, so it’s about time to discuss the new version of the language. The seventh version of C# continues the trend started by its predecessor. This trend is all about making the code cleaner and more concise. There are no radically new capabilities in the language. In this version, the design team improved certain features that were introduced in C# 6. It seems that after a trial run in the previous version, the design team found out which features were well accepted to they could be taken to the next level
Out variables
Until version 7, the usage of the out keyword was always a bit cumbersome. First you had to declare the variable and then use it. In C# 7 we can declare and use a variable with the out keyword in a single line. Like this.
// previous version
int age;
if (int.TryParse(ageTextBox.Text, out age))
WriteLine(age);
else
WriteLine("Age is not a valid integer!");
// C# 7
if (int.TryParse(ageTextBox.Text, out int age))
WriteLine(age);
else
WriteLine("Age is not a valid integer!");
You should, however, bear a few important things in mind:
- Even though the type name is explicitly written in the declaration, it’s not always required. We could have used var and it would work just the same.
- It’s easy to think think that the declared variable will go out of scope after we leave the if/else block. However, that is not the case. The variable continues to be accessible until going out of its normal scope.
throw Expressions
In C# 7, we can throw an exception directly through expression. Thus, an exception can be thrown from an expression. Consider this snippet.
public CustomerService(ICustomerRepository repository)
{
if (repository == null)
{
throw new ArgumentNullException(nameof(repository));
}
this.repository = repository;
}
That’s quite a number of lines, just to to assign an object of a certain type to a property. It’s simply a guard clause, which can be important, but with so many lines, you can imagine that with having multiple of these around your code becomes pretty messy. In the previous versions of C#, throw was a statement. In C#7, it is an expression, which allows us to throw exceptions in places like the second hand of the Null Coalescing Operator and in conditional expressions. Here are a few examples.
public CustomerService(ICustomerRepository repository)
{
this.repository = repository ?? throw new ArgumentNullException(nameof(repository));
}
class Person
{
public string Name { get; }
public Person(string name) => Name = name ?? throw new ArgumentNullException(name);
public string GetFirstName()
{
var parts = Name.Split(" ");
return (parts.Length > 0) ? parts[0] : throw new InvalidOperationException("No name!");
}
public string GetLastName() => throw new NotImplementedException();
}
Expression-bodied members
C# 6 already brought us Expression-bodies members. They are a nice and shorter way of writing members of the class, using a lambda expression syntax. C# 7.0 adds accessors, constructors and finalizers to the list of things that can have expression bodies. So we’re no longer limited to using them in methods, read-only properties and indexers.
class Person
{
private static ConcurrentDictionary<int, string> names = new ConcurrentDictionary<int, string>();
private int id = GetId();
public Person(string name) => names.TryAdd(id, name); // constructors
~Person() => names.TryRemove(id, out *); // destructors
public string Name
{
get => names[id]; // getters
set => names[id] = value; // setters
}
}
Digit separators and binary literals
Take a look at the the following code.
var d = 123_456;
var x = 0xAB_CD_EF;
What are these underscores doing there? It’s for readability. Large numbers can become quite hard to read. To address this issue, C# 7 lets you to use the _ as a digit separator. You can put them wherever you want between digits, to improve readability. They have no effect on the value. Also, C# 7.0 introduces binary literals, so that you can specify bit patterns directly instead of having to know hexadecimal notation by heart.
var b = 0b1010_1011_1100_1101_1110_1111;
If you need to write a binary value, just put 0b at the beginning of the number, and that’s all.
Conclusion Most of the new C# 7 features should not come as a surprise. The language design team communicates openly with the community about the direction C# is going. An early post on the features was posted last year already. And meeting notes and proposals are shared on github. So, the design team didn’t just include some random new features just for the sake of it; instead, they carefully selected the ones that would help all of us to improve the quality of our code. I hope you enjoy them.
Leave a Comment