Vaughan Reid's blog

C# 9.0: Readability improvements

With the recent announcement of .NET 5.0 I’d like to spend some time going over some of the nice features you will get out the box if you upgrade.

With .NET 5.0, you can start using C# 9.0 features and it has some nifty syntax changes that I think can make your code a little nicer to read. When features come out in a language, instead of just using it, I personally try to decide if it makes my code more readable. For me it needs to remove boilerplate code or make existing code more succinct. I think a couple of these achieve this which is great.

Let me use my patented Person™ class to showcase some of the changes.


public class Person
{
	public string Name { get; set; }
	public int Age { get; set; }
}

I combined a couple of these features into a single class to get a good feel on how they could fit together.


public class Program
{
	static bool IsAdult(Person p) => p is not null and { Age: >= 18 };
	static bool IsChild(Person p) => p is not null and { Age: < 13 };
	static bool IsTeenager(Person p) => p is not null and { Age: < 18 and > 13 };

	public static void Main(string[] args)
	{
		var people = new Person[]
		{
			new (){ Name = "John", Age = 10 },
			new (){ Name = "Sally", Age = 15 }
		};

		foreach (var p in people)
		{
			if (IsAdult(p))
			{
				Console.WriteLine($"{p.Name} is an adult");
			}

			if (IsTeenager(p))
			{
				Console.WriteLine($"{p.Name} is a teenager");
			}

			if (IsChild(p))
			{
				Console.WriteLine($"{p.Name} is a child");
			}
		}

		object something = new Person { Name = "Eric", Age = 100 };

		if (something is Person person)
		{
			if (IsAdult(person))
			{
				Console.WriteLine($"{person.Name} is an adult");
			}
		}
	}
}

Let me break down some of those changes for you.

Property patterns

I really like property patterns. As much as I avoid one liner methods I think this syntax makes the implementation really clear.

static bool IsTeenager(Person p) => p is not null and { Age: < 18 and > 13 };

Before property patterns I would have had to do this. Its not terrible but it could start getting very verbose.


static bool IsTeenager(Person p) => p != null && p.Age < 18 && p.Age > 13;

Target-typed new

Its a very small change where if a type can be inferred, you can just use parenthesis when creating a new instance. A nice use case for this is when using an array initializer.


var people = new Person[]
{
	new (){ Name = "John", Age = 10 },
	new (){ Name = "Sally", Age = 20 }
};

Logical pattern

Its a small change but it removes a line of code. Less code means less bugs to me! When checking if an object is a type, you can create a variable of that type without an additional typecasting line. In the below case, if something is a Person then I can use my person variable in the next line.


object something = new Person { Name = "Eric", Age = 100 };

if (something is Person person)
{
	if (IsAdult(person))
	{
		Console.WriteLine($"{person.Name} is an adult");
	}
}