Is there a convention to the order of modifiers in C#?

I had a look at Microsoft’s Framework Design Guidelines and couldn’t find any references to what order modifiers should be put on members. Likewise, a look at the C# 5.0 language specification proved fruitless. There were two other avenues to follow, though: EditorConfig files and ReSharper.


.editorconfig

The MSDN page, .NET coding convention settings for EditorConfig says:

In Visual Studio 2017, you can define and maintain consistent code style in your codebase with the use of an EditorConfig file.

Example EditorConfig file

To help you get started, here is an example .editorconfig file with the default options:

###############################
# C# Code Style Rules         #
###############################

# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion

In other words: the default order for modifiers, following the default editorconfig settings is:

{ public / private / protected / internal / protected internal / private protected } // access modifiers
static
extern
new
{ virtual / abstract / override / sealed override } // inheritance modifiers
readonly
unsafe
volatile
async

ReSharper

ReSharper, however, is more forthcoming. The defaults for ReSharper 2018.11, with access modifiers (which are exclusive) and inheritance modifiers (which are exclusive), grouped together is:

{ public / protected / internal / private / protected internal / private protected } // access modifiers
new
{ abstract / virtual / override / sealed override } // inheritance modifiers
static
readonly
extern
unsafe
volatile
async

This is stored in the {solution}.dotsettings file under the

"/Default/CodeStyle/CodeFormatting/CSharpFormat/MODIFIERS_ORDER/@EntryValue"

node – the ReSharper default2 is:

<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MODIFIERS_ORDER/@EntryValue">
    public protected internal private new abstract virtual sealed override static readonly extern unsafe volatile async
</s:String>

1 ReSharper 2018.1 says that it has “Full understanding of C# 7.2” and explicitly mentions the private protected access modifier.

2 ReSharper only saves settings which differ from the default, so in general this node, as it is, will not be seen in the dotsettings file.


new static vs static new

The MSDN page for Compiler Warning CS0108 gives the example of a public field i on a base class being hidden by a public static field i on a derived class: their suggestion is to change static to static new:

public class clx
{
    public int i = 1;
}

public class cly : clx
{
    public static int i = 2; // CS0108, use the new keyword
    // Use the following line instead:
    // public static new int i = 2;
}

Likewise, the IntelliSense in Visual Studio 2015 also suggests changing static to static new

CS0108 Visual Studio recommended change

which is the same if the field i in the base class is also static.

That said, a cursory search on GitHub found that some projects override this default to put static before, not after new, the inheritance modifiers and sealed, e.g.
the ReSharper settings for StyleCop GitHub project:

<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MODIFIERS_ORDER/@EntryValue">
    public protected internal private static new abstract virtual override sealed readonly extern unsafe volatile async
</s:String>

however since static cannot be used in conjunction with the inheritance modifiers or sealed, this is just a distinction between new static (the default, and suggested by the default editorconfig file) and static new (suggested by ReSharper).

Personally I prefer the latter, but Google searches in referencesource.microsoft.com for new static vs static new in 2015 and 2018 gave:

             (in 2015)  (in 2018)
new static   203        427
static new   10         990

which implies that the preference at Microsoft is static new.

Leave a Comment