Oops, I thought this had been published a long time ago, but oh well: it is never too late to publish reflections on a C# programming language improvement.
After recovering from my rectum cancer treatments and finally upgrading most of my projects to recent enough C# versions, it was time to catch up on useful little C# language features released during my treatments.
This one is really nice: [Wayback/Archive] File scoped namespaces – C# 10.0 draft specifications | Microsoft Learn.
I wish it had been released much earlier, as it so much reminds me of the unit
keyword in Delphi which influenced C# a lot. Well, actually the unit
actually started in UCSD Pascal and Turbo Pascal; UCSD Pascal ran on the UCSD p-Machine (more on that in a future blog post), which influenced the Java Virtual Machine, which was based on Java bytecode and a Just-in-time compiler in turn influenced the .NET Common Language Runtime.
There are many examples from other languages, paradigms and frameworks: I love how C# and .NET bring so much programming history together.
In Delphi it is easy: a source file can contain at maximum one unit (and apart from files included in that source file, no other source files can contribute to that unit) and the filename needs to match the unitname, so the unit is a self contained namespace.
In practice, in C# it is just as easy: despite that you can have multiple namespaces in one source file, few source files do.
So it was finally time to simplify that, by introducing
File scoped namespaces
This means that a file with just a single traditional C# (pre version 10) namespace syntax like this:
namespace FooNamespace { // Members }
can now become, saving indentation and curly braces:
A namespace is defined like this:
namespace FooNamespace; // Members
of like [Wayback/Archive] File scoped namespaces – C# 10.0 draft specifications | Microsoft Learn describes:
File scoped namespaces use a less verbose format for the typical case of files containing only one namespace. The file scoped namespace format is
namespace X.Y.Z;
(note the semicolon and lack of braces). This allows for files like the following:namespace X.Y.Z; using System; class X { }
The semantics are that using the
namespace X.Y.Z;
form is equivalent to writingnamespace X.Y.Z { ... }
where the remainder of the file following the file-scoped namespace is in the...
section of a standard namespace declaration.…
Analysis of the C# ecosystem shows that approximately 99.7% files are all of either one of these forms:
namespace X.Y.Z { // usings // types }
or
// usings namespace X.Y.Z { // types }
…
and then continues with the specifications (which I won’t cover here: they do a great job on it already).
IDEs and file scoped namespaces
Despite file scoped namespaces being in C# 10, actively using them was not the default yet at the end of 2021. I think that is reasonable as for coding standards you need to have consensus in projects, solutions or/and teams.
This is why Visual Studio (and other IDEs: it is a global standard, works in JetBrains Rider and might work in Visual Studio Code as well) has .editorconfig
files on the level of projects and solutions (and users in the form of global config files) shown in these two questions and answers:
- [Wayback/Archive] c# – How can I use a file-scoped namespace declaration in a class template? – Stack Overflow (thanks, [Wayback/Archive] Nigel and [Wayback/Archive] niels013)
Q
C# 10 introduced file-scoped namespaces, which I would like to use in Visual Studio’s class templates. I’ve updated the ‘Class’ template file to the following:namespace $rootnamespace$; class $safeitemrootname$ { //I put this comment here to make sure it's using the right file }
But when I create a new empty class I get this autogenerated code:namespace ProjectName { internal class Class1 { //I put this comment here to make sure it's using the right file } }
What do I need to do to make the auto-generated code for an empty class look like this?namespace ProjectName; internal class Class1 { }
For reference, I am using Visual Studio 2022 Professional and my project is using C#10 with .NET 6.The location of the class template file that I am modifying is:C:Program FilesMicrosoft Visual Studio2022ProfessionalCommon7IDEItemTemplatesCSharpCode1033ClassClass.cs
A
You have to set up your project’s editorconfig to prefer File-scoped namespaces.-
Right click your project. Select “Add” → “New Item”
-
Select “editorConfig File (.NET)”
-
Double click the new editorconfig file. In the “Code Style” tab set “Namespace declarations” to “File scoped”
A
Check this thread: https://stackoverflow.com/a/69889803They use a.editorconfig
file where you can specify the namespace declaration style. When creating a new file in VS 2022 it will use that new style -
- [Wayback/Archive] c# – VS 2022 – Convert to file-scoped namespace in all files – Stack Overflow (thanks [Wayback/Archive] Mirek, [Wayback/Archive] Guru Stron, [Wayback/Archive] Emilija Vilija Trečiokaitė , [Wayback/Archive] KUTlime and [Wayback/Archive] Caius Jard)
Q
I’m converting my project to .NET 6 and I want to use filescoped namespaces everywhere. But the conversion tool exists only in the editor.A (project or solution scope)
Adding a rule to use file scoped namespaces in
.editorconfig
worked for me:- create an
.editorconfig
file in the solution directory - add following line/content below (docs, code – IDE0161)
Example
.editorconfig
file content:[*.cs] csharp_style_namespace_declarations = file_scoped:warning
After that the preview changes dialog had an option to apply the fix to the whole project/solution:
A (global user scope)
[Wayback/Archive] www.ilkayilknur.com/how-to-convert-block-scoped-namespacees-to-file-scoped-namespaces
It says that you can change the code-style preference (and enable the display of the option to apply this preference in a document / project / solution) by going to Tools => Options => Text Editor => C#=> Code Style and then changing the related preference.
C
You don’t want to do that, because that is IDE level. You can generate literally thousands of merge changes/conflict by this change.
C
That’s why as a team you agree when to make such a change and you do it in isolation and get everyone on the same page before continuing more work..?
- create an
The last answer linked to a post [Wayback/Archive] How To Convert Block Scoped Namespaces To File Scoped Namespaces which was based on the middle of this 3 part blog series:
- [Wayback/Archive] How to enforce a consistent coding style in your projects – Meziantou’s blog
- [Wayback/Archive] Enforce .NET code style in CI with dotnet format – Meziantou’s blog
- [Wayback/Archive] Running GitHub Super-Linter in Azure Pipelines – Meziantou’s blog
The series will come in
Updating your project or solution to file scoped namespaces automatically
Manually changing all the files in your projects or solutions to use is time consuming, so I was glad to find [Wayback/Archive] Updating your project to use File Scoped Namespaces – Meziantou’s blog:
you can usedotnet format
to fix your code style:dotnet tool update --global dotnet-format dotnet format MySolution.sln --severity info --diagnostics=IDE0161
Note that you can remove--diagnostics=IDE0161
to fix all code style issues.
For the other way around, use IDE0160
in stead of IDE0161
as per [Wayback/Archive] Namespace declaration preferences (IDE0160 and IDE0161) – .NET | Microsoft Learn:
Property Value Rule ID IDE0160 Title Use block-scoped namespace Category Style Subcategory Language rules (namespace preferences) Applicable languages C# Options csharp_style_namespace_declarations
Property Value Rule ID IDE0161 Title Use file-scoped namespace Category Style Subcategory Language rules (namespace preferences) Applicable languages C# Options csharp_style_namespace_declarations
csharp_style_namespace_declarations
permutations
In the .editorconfig
, there can be various permutations of this:
[*.cs] csharp_style_namespace_declarations = file_scoped:warning
The first part that can vary is before the :
colon as per [Wayback/Archive] Namespace declaration preferences (IDE0160 and IDE0161) – .NET | Microsoft Learn and [Wayback/Archive] c# – EditorConfig control File-scoped namespace declaration – Stack Overflow (thanks [Wayback/Archive] JuChom and [Wayback/Archive] KUTlime):
block_scoped
file_scoped
The second part that can very is after the :
colon as per [Wayback/Archive] Analyzer configuration – Visual Studio (Windows) | Microsoft Learn:
default
none
(which used to besuppress
)silent
orrefactoring
(which both were used to behidden
)suggestion
(which used to beinfo
)warning
(which used to bewarn
)error
Which means there are 12 permutations.
The [Wayback/Archive] Analyzer configuration – Visual Studio (Windows) | Microsoft Learn contains this helpful table showing the various behaviours:
Severity (Solution Explorer) Severity (EditorConfig file) Build-time behavior Editor behavior Error error
Violations appear as Errors in the Error List and in command-line build output, and cause builds to fail. Offending code is underlined with a red squiggle and marked by a small red box in the scroll bar. Warning warning
Violations appear as Warnings in the Error List and in command-line build output, but don’t cause builds to fail. Offending code is underlined with a green squiggle and marked by a small green box in the scroll bar. Info suggestion
Violations appear as Messages in the Error List, and not at all in command-line build output. Offending code is underlined with a gray squiggle and marked by a small gray box in the scroll bar. Hidden silent
Non-visible to user. Non-visible to user. The diagnostic is reported to the IDE diagnostic engine, however. None none
Suppressed completely. Suppressed completely. Default default
Corresponds to the default severity of the rule. To determine what the default value for a rule is, look in the Properties window. Corresponds to the default severity of the rule.<t
In the past, some of these values were different as you can see in [Wayback/Archive] Different .editorconfig severity strings are used to specify IDE code style options and dotnet_diagnostic.severity · Issue #35690 · dotnet/roslyn
DiagnosticSeverity IDE Code style term Compiler dotnet_diagnostic.severity term Error “error” “error” Warning “warning” “warn” Info “suggestion” “info” Hidden “silent” or “refactoring” “hidden” Suppress “none” “suppress”
That got fixed in [Wayback/Archive] Change dotnet_diagnostic.*.severity settings to match code style by jasonmalinowski · Pull Request #36566 · dotnet/roslyn.
Not yet fixed at the time of writing was [Wayback/Archive] Deprecate ‘severity’ field for IDE code style editorconfig syntax · Issue #44201 · dotnet/roslyn and makes it harder to synchronise code editor and continuous integration behaviour.
Also not fixed at the time of writing was [Wayback/Archive] csharp_style_namespace_declarations causes compilation errors with #region directives · Issue #1509 · dotnet/format.
Hopefully by now both are fixed by now.
More on .editorconfig
files
I was relatively new on .editorconfig
files, so here are some links for my archive:
- [Wayback/Archive] .NET code style rule options – .NET | Microsoft Learn starts with:
You can define and maintain consistent code style in your codebase by defining .NET code-style rules and their associated options in a configuration file. These rules are surfaced by various development IDEs, such as Visual Studio, as you edit your code. For .NET projects, these rules can also be enforced at build time. You can enable or disable individual rules and configure the degree to which you want each rule enforced, via a severity level.
The article continues with
.editorconfig
information mainly in the context of Visual Studio, but the information applies in similar ways to other integrated development environments like Visual Studio Code and Rider from JetBrains (which like Visual Studio Code is cross platform, but more rich in functionality, similar to Visual Studio). - [Wayback/Archive] EditorConfig settings – Visual Studio (Windows) | Microsoft Learn
EditorConfig settings take precedence over global Visual Studio text editor settings. This means that you can tailor each codebase to use text editor settings that are specific to that project. You can still set your own personal editor preferences in the Visual Studio Options dialog box. Those settings apply whenever you’re working in a codebase without an .editorconfig file, or when the .editorconfig file doesn’t override a particular setting. An example of such a preference is indent style—tabs or spaces.
- [Wayback/Archive] RehanSaeed/EditorConfig: A very generic .editorconfig file supporting .NET, C#, VB and web technologies.
- [Wayback/Archive] EditorConfig (
editorconfig.org
)
What is EditorConfig?
EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.
…
File Format Details
EditorConfig files use an INI format that is compatible with the format used by Python ConfigParser Library, but [ and ] are allowed in the section names. The section names are filepath globs (case sensitive), similar to the format accepted by gitignore. Only forward slashes (/, not backslashes) are used as path separators and octothorpes (#) or semicolons (;) are used for comments. Comments should go on their own lines. EditorConfig files should be UTF-8 encoded, with either CRLF or LF line separators. EditorConfig files are read top to bottom and the most recent rules found take precedence.
…
- [Wayback/Archive] Configuration files for code analysis rules – .NET | Microsoft Learn has excellent material, including these sections:
- [Wayback/Archive] Configuration files for code analysis rules: EditorConfig – .NET | Microsoft Learn
- [Wayback/Archive] Configuration files for code analysis rules: Global AnalyzerConfig – .NET | Microsoft Learn which has a slightly different format than
.editorconfig
files as they apply to the whole project; if you name them with extension.globalconfig
then they apply in that directory and all its subdirectories.
Via
- [Wayback/Archive] Iris Classon, #MSBuild Dev MC on Twitter: “What is your favorite (newer) C# language feature?”
- [Wayback/Archive] Jon Skeet on Twitter: “@IrisClasson File-scoped namespaces. Such a trivial and universally-applicable feature, so much indentation removed.”
- [Wayback/Archive] “File-scoped namespaces” – Google Search
- [Wayback/Archive] csharp_style_namespace_declarations – Google Search
- [Wayback/Archive] “file_scoped:warning” “file_scoped:suggestion” – Google Search (which at the time of writing had zero results!)
- [Wayback/Archive] .editorconfig warning suggestion – Google Search
- [Wayback/Archive] .editorconfig warning suggestion severity – Google Search
- [Wayback/Archive] “.editorconfig file” – Google Search
- [Wayback/Archive] .editorconfig file global – Recherche Google
Related blog posts
--
jeroen