C# 8.0 came out in the fall of 2019. Here are some of my favorite additions to the language
Nullable Reference types
This feature is implemented with the express purpose of reducing NullReferenceExceptions
by attempting to catch these at compile time. Nullable reference types don’t specifically solve this problem, but they are step towards that goal.
Yes, reference types are already nullable. However if we introduce the concept of a non-nullable reference type, we create means of allowing the compiler to flag code that is potentially create a null-ed reference situation. But...to do that properly (and for backward compatibility), it helps to identify whether a reference type is null-able or not. Hence: the creation of "Nullable" reference types.
Default interface implementations
This is a nice feature because it adds the ability to provide a default implementation on an interface method. I can certainly say there have been times in the past when this would have been nice to have. Here's an example of what that looks like:
1 2 3 4 5 6 7 | interface ILogger { void Write(string text) { Console.WriteLine(text); } } |
Advanced Pattern patching
Allows for pattern matching on the data structure of an object. Looks like this:
1 2 3 4 5 6 | var point = new 3DPoint(1, 2, 3); //x=1, y=2, z=3 if (point is 3DPoint(1, var myY, _)) { // Code here will be executed only if the point .X == 1, myY is a new variable // that can be used in this scope. } |
Property pattern matching in switch statements
First, this example introduces two concepts here, one being the "switch statement" using a lambda terminology.
This also shows the use of switching on a property value within the object being switched on. In this case, a location is the target of the switch statement, but the cases look at a specific property (State):
1 2 3 4 5 6 7 8 9 | public static decimal ComputeSalesTax(Address location, decimal salePrice) => location switch { { State: "WA" } => salePrice * 0.06M, { State: "MN" } => salePrice * 0.075M, { State: "MI" } => salePrice * 0.05M, // other cases removed for brevity... _ => 0M }; |