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>
1ReSharper 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
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
.
StyleCop is available as a Visual Studio extension or a NuGet package and can validate your source code against the rules some teams in Microsoft use. StyleCop likes the access modifier to come first.
EDIT: Microsoft isn't itself totally consistent; different teams use different styles. For example StyleCop suggests putting using directives in the namespace, but this is not followed in the Roslyn source code.