Quantcast
Channel: Java – The Wiert Corner – irregular stream of stuff
Viewing all articles
Browse latest Browse all 67

File scoped namespaces – C# 10.0 draft specifications | Microsoft Learn

$
0
0

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 writing namespace 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.
    1. Right click your project. Select “Add” → “New Item”
    2. Select “editorConfig File (.NET)”
    3. Double click the new editorconfig file. In the “Code Style” tab set “Namespace declarations” to “File scoped”

    A

    They 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.

    file-scoped namespace conversion

    Has anyone found out if there’s a way to run this editor function across all files in solution at once? (Looks like Rider has that function)

    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 (docscode – 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:

    enter image description here

    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. enter image description here

    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..?

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:

  1. [Wayback/Archive] How to enforce a consistent coding style in your projects – Meziantou’s blog
  2. [Wayback/Archive] Enforce .NET code style in CI with dotnet format – Meziantou’s blog
  3. [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 use dotnet 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 be suppress)
  • silent or refactoring (which both were used to be hidden)
  • suggestion (which used to be info)
  • warning (which used to be warn)
  • 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:

Via

Related blog posts

--jeroen


Viewing all articles
Browse latest Browse all 67

Trending Articles