Two Favorite C# 10 Features

19 Oct 2021

C# 10 is being released in November 2021 along with .NET 6. There are several new language features being released. You can read about them here. The list has some interesting features, most of which are solutions to problems that I don't have.

The two (2) new features that excite me appeal directly to a desire to write less code, or at the very least, a chance to be more efficient with the code that I do wind up writing.

Global using directives

This language feature is a modifier that has been added to the existing using directive. You can read the official documentation for the global modifier.

By applying this modifier to a using directive the directive will be available in all files in the project. I like to think of this as an #include from the good ol' days. Just remember that the global directive must first and before your namespace declaration.

This block of using directives gets added to pretty much every source file I am working on lately. Using this new feature I create a Globals.cs file and add it the project. I prefer this method to the csproj addition of the <Using /> element. To me, it makes more sense to have a visible file, clearly named, rather than relying upon developers to check the project file.

global using System;                     // for all files (if needed or not)
global using System.Collections.Generic; // obvious reasons
global using System.Linq;                // makes playing with collections better
global using System.Threading.Tasks;     // mostly for web projects

This method of including namespaces does not affect the .NET from removing assemblies when it is publishing a trimmed self-contained deployment.

File-scope namespace declaration

This new feature is pure syntax gold. Why? I do not think I have ever created multiple namespaces within a single source file. I know it can be done, but it is not my normal convention: single namespace, single class per file. I have found that be a reasonable approach to organizing code. Of course, there are exceptions but never for multiple namespaces.

using System;                     // for all files (if needed or not)
using System.Collections.Generic; // obvious reasons
using System.Linq;                // makes playing with collections better
using System.Threading.Tasks;     // mostly for web projects

namespace TheNamespace
{
  // Everything is now tabbed over - 4 spaces!
  public class SampleClass { }
}

That is why the file-scoped namespace feature makes so much sense to me. It saves me code and give me back an entire level of indenting. When combined with global using directives the above code becomes:

namespace TheNamespace;
// Everything is now tabbed over - 4 spaces!
public class SampleClass { }

This works for me!

Conclusion = Less Typing

The reality is that these two (2) features are really just syntactic sugar. We currently get the same result by typing some extra characters. The compiler will still produce the same code. So why be lazy?

Frankly, I feel that file-scoped namespace is just being lazy ... for sure. I will take it, however, because it is useful. The global using directives saves time. If kept in a Globals.cs or similar file it provides a clear understanding of what to expect for the project. There is no digging in the csproj file. It can handle additions clearly and simply. Once a team decides that is how they are going to manage their code, it documents itself.

Updated: edited using block code to include global to be more clear.

< back