About

A .editorconfig file can apply to any language. It is used by an IDE to enforce coding conventions.

In .Net, file .editorconfig is located at solution/project root.

.editorconfig uses INI format.
.editorconfig files should be UTF-8 encoded, with LF or CRLF line separators

[editorconfig.org]

Interpreter

.editorconfig files can be used in a hierarchy.

Lower-level configs override higher-level configs.

Set "root=true" in the preamble to say "don't look for a high-level config, this is it".

Anywhere a .editorconfig is found when in your project, the IDE searches upward in the directories until it finds a "root" or reaches the root of the filesystem.

.editorconfig files are read top-to-bottom.
Lower-down rules can override higher-up rules.
Format

Leading whitespaces are ignored.

Lines can be:
- blank
- comments
- section header
- key-value pair

Preamble

The preamble is everything above the first Section Header.

Optional.

Setting "root=true" means don't search in parent directories for more .editorconfig. This is the root.

    # http://editorconfig.org
    root = true

Comments

Comments are lines starting with ; or #
Only full-line comments are allowed

Section Header

Section headers are enclosed in [ ]
- uses / as path separator on all operating systems

Section Name

Section name is the text between the [ ]

Section names are filepath Globs and support pattern matching
- * for any string of characters, except for path separators
- ** for any string of characters
- ? for any single character
- [abc] for any single character in the defined group
- [!abc] for any single character not in the defined group
- {s1,s2,s3} for any string defined in the set
- {num1..num2} for any integer defined in the range (negatives are allowed)
- \ to escape a special character
- Section names have a max length of 4096
- Non-existing directories will not cause an error

Ex:
[*] will apply to all files in the project
[*.md] will apply to all Markdown files in the project
[*.{cs,vb}] will apply to all CS and all VB files in the project

Section

A section is all the lines from one section header to the next, or to the end of file.

Key-Value Pair

Key-Value pair looks like Key=Value or Key = Value
- strings are not enclosed in "quotes"

Any key-value pair can be disregarded with an unset command

 # set a value
 insert_final_newline = true
 
 # ignore that value
 insert_final_newline = unset

Example


 # http://editorconfig.org
 root = true
 
 # Global settings
 [*]
 max_line_length = 0
 charset = utf-8
 indent_size = 2
 indent_style = space
 insert_final_newline = true
 trim_trailing_whitespace = true
 
 # Markdown
 [*.md]
 trim_trailing_whitespace = false
 
 # Dotnet code style settings
 [*.{cs,vb}]
 indent_size = 4
 indent_style = tab
 
 # Sort using and Import directives with System.* appearing first
 dotnet_sort_system_directives_first = true
 
 # Avoid "this." and "Me." if not necessary
 dotnet_style_qualification_for_field = false:error
 dotnet_style_qualification_for_property = false:error
 dotnet_style_qualification_for_method = false:error
 dotnet_style_qualification_for_event = false:error
Universal Keys

Key-Value pairs recognised by all parsers.

[editorconfig Specification]

Root

Only use in the preamble. Specify this file as the root config.

 root = true

Indent_style


 # use hard tabs
 indent_style = tab
 
 # use soft tabs
 indent_style = space

Indent_size

Defines the number of indent characters to use at each level.


 # whole number
 indent_size = 4
 
 # use the tab_width value
 indent_size = tab

Tab_width

Defines the number of columns (characters widths) used to represent a tab.
Defaults to indent_size if tab_width is not specified.


 # whole number
 tab_width = 4

End_of_line


 # carriage return
 end_of_line = cr

 # carriage return + line feed
 end_of_line = crlf

 # line feed
 end_of_line = lf

Charset


 charset = latin1
 charset = utf-8
 charset = utf-8-bom
 charset = utf-16be
 charset = utf-16le

Trim_trailing_whitespace


 # remove whitespace that preceeds a newline
 trim_trailing_whitespace = true

 # leave the whitespace as is
 trim_trailing_whitespace = false

Insert_final_newline


 # ensure file's last character is a newline
 insert_final_newline = true

 # doesn't care
 insert_final_newline = false

.Net Language Keys

Key-Value pairs recognised by .Net IDEs.

[documentation]

Value format is "value:severity".

Severity

error - violation causes compiler error (this does not stop a build)

warning - violation causes compiler warning

suggestion - violation causes a suggestion (such as three gray dots under the code)

silent - violation causes nothing, but suggestion appears in the Refactorings menu, and auto-generated code uses this style
aka refactoring

none - violation causes nothing, but auto-generated code uses this style

This Qualifiers

"true" means you should qualify members with the "this" keyword. ("me" is the Visual Basic version of "this")

"false" means you should not qualify members with the "this" keyword.


[*.{cs,vb}]
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion

Framework Type Names

"true" means you should say "int" instead of "Int32".

"false" means you should say "Int32" instead of "int".


[*.{cs,vb}]
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion

Modifiers

Should accessibility modifiers be specified? (private, public, protected)

[*.{cs,vb}]
dotnet_style_require_accessibility_modifiers = always:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
dotnet_style_require_accessibility_modifiers = never:suggestion
dotnet_style_require_accessibility_modifiers = omit_if_default:suggestion
"for_non_interface_members" currently works the same as "always".

When this rule is set, it is set to an ordered list of modifiers. This is the order preferred in the code.

[*.cs]
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion

[*.vb]
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion

Should a field that CAN be marked "readonly", be marked such?

[*.{cs,vb}]
dotnet_style_readonly_field = true:warning

Parentheses

Prefer "a + (b * c)" over "a + b * c"

[*.{cs,vb}]
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:silent

Prefer "(a < b) == (c > d)" over "a < b == c > d"

[*.{cs,vb}]
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:silent

Prefer "a || (b && c)" over "a || b && c"

[*.{cs,vb}]
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:silent

Prefer "(a.b).Length" over "a.b.Length"

[*.{cs,vb}]
dotnet_style_parentheses_in_other_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent

Expression-level


 [*.{cs,vb}]
 # prefer var c = new Customer() { Age = 21 };
 dotnet_style_object_initializer = true:suggestion

 # prefer var c = new Customer(); c.Age = 21;
 dotnet_style_object_initializer = false:suggestion


 [*.{cs,vb}]
 # prefer var list = new List<int> { 1, 2, 3 };
 dotnet_style_collection_initializer = true:suggestion

 # prefer var list = new List<int>(); list.Add(1); list.Add(2); list.Add(3);
 dotnet_style_collection_initializer = false:suggestion


 [*.{cs,vb}]
 # prefer (string name, int age) customer = GetCustomer(); var name = customer.name;
 dotnet_style_explicit_tuple_names = true:suggestion
 
 # prefer (string name, int age) customer = GetCustomer(); var name = customer.Item1;
 dotnet_style_explicit_tuple_names = false:suggestion


 [*.{cs,vb}]
 # prefer var tuple = (age, name);
 dotnet_style_prefer_inferred_tuple_names = true:suggestion

 # prefer var tuple = (age: age, name: name);
 dotnet_style_prefer_inferred_tuple_names = false:suggestion


 [*.{cs,vb}]
 # prefer var anon = new { age, name };
 dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion

 # prefer var anon = new { age = age, name = name };
 dotnet_style_prefer_inferred_anonymous_type_member_names = false:suggestion


 [*.{cs,vb}]
 # prefer private int Age { get; }
 dotnet_style_prefer_auto_properties = true:silent

 # prefer private int age; public int Age { get { return age; } }
 dotnet_style_prefer_auto_properties = false:silent


 [*.{cs,vb}]
 # prefer if (value is null) return;
 dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion

 # prefer if (object.ReferenceEquals(value, null)) return;
 dotnet_style_prefer_is_null_check_over_reference_equality_method = false:suggestion


 [*.{cs,vb}]
 # prefer string s = expr ? "hello" : "world";
 dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion

 # prefer string s; if (expr) { s = "hello"; } else { s = "world"; }
 dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion


 [*.{cs,vb}]
 # prefer return expr ? "hello" : "world"
 dotnet_style_prefer_conditional_expression_over_return = true:suggestion

 # prefer if (expr) { return "hello"; } else { return "world"; }
 dotnet_style_prefer_conditional_expression_over_return = false:suggestion


 [*.{cs,vb}]
 # prefer x += 1;
 dotnet_style_prefer_compound_assignment = true:suggestion

 # prefer x = x + 1;
 dotnet_style_prefer_compound_assignment = false:suggestion


 [*.cs]
 # prefer void DoWork(CancellationToken cancellationToken = default) { ... }
 csharp_prefer_simple_default_expression = true:suggestion

 # prefer void DoWork(CancellationToken cancellationToken = default(CancellationToken)) { ... }
 csharp_prefer_simple_default_expression = false:suggestion

Null Checking


 [*.{cs,vb}]
 # prefer var v = x ?? y;
 dotnet_style_coalesce_expression = true:suggestion

 # prefer var v = x != null ? x : y;
 dotnet_style_coalesce_expression = false:suggestion


 [*.{cs,vb}]
 # prefer var v = o?.ToString();
 dotnet_style_null_propagation = true:suggestion

 # prefer var v = o == null ? null : o.ToString();
 dotnet_style_null_propagation = false:suggestion


 [*.cs]
 # prefer this.s = s ?? throw new ArgumentNullException(nameof(s));
 csharp_style_throw_expression = true:suggestion

 # prefer if (s == null) { throw new ArgumentNullException(nameof(s)); } this.s = s;
 csharp_style_throw_expression = false:suggestion


 [*.cs]
 # prefer func?.Invoke(args);
 csharp_style_conditional_delegate_call = true:suggestion

 # prefer if (func != null) { func(args); }
 csharp_style_conditional_delegate_call = false:suggestion

Parameters

Prefer that unused method parameters are removed from the method signature.

 [*.{cs,vb}]
 # apply to all methods
 dotnet_code_quality_unused_parameters = all:suggestion
 
 # apply to non-public methods only
 dotnet_code_quality_unused_parameters = non_public:suggestion

Implicit And Explicit Types


 [*.{cs}]
 # prefer var x = 5;
 csharp_style_var_for_built_in_types = true:suggestion
 
 # prefer int x = 5;
 csharp_style_var_for_built_in_types = false:suggestion


 [*.{cs}]
 # prefer var obj = new Customer();
 csharp_style_var_when_type_is_apparent = true:suggestion
 
 # prefer Customer obj = new Customer();
 csharp_style_var_when_type_is_apparent = false:suggestion


 [*.{cs}]
 # prefer var f = this.Init();
 csharp_style_var_elsewhere = true:suggestion
 
 # prefer bool f = this.Init();
 csharp_style_var_elsewhere = false:suggestion

Expression-bodied Members

"true" means the expression-body is preferred over block-body.

"false" means the block-body is preferred over the expression-body.

"when_on_single_line" means expression-body is preferred when it results in a single line.


 [*.{cs}]
 csharp_style_expression_bodied_methods = false:silent
 csharp_style_expression_bodied_constructors = false:silent
 csharp_style_expression_bodied_operators = false:silent
 csharp_style_expression_bodied_properties = true:suggestion
 csharp_style_expression_bodied_indexers = true:suggestion
 csharp_style_expression_bodied_accessors = true:suggestion
 csharp_style_expression_bodied_lambdas = true:silent
 csharp_style_expression_bodied_local_functions = false:silent

Pattern Matching


 [*.{cs}]
 # prefer if (o is int i) {...}
 csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion

 # prefer if (o is int) {var i = (int)o; ... }
 csharp_style_pattern_matching_over_is_with_cast_check = false:suggestion


 [*.{cs}]
 # prefer if (o is string s) {...}
 csharp_style_pattern_matching_over_as_with_null_check = true:suggestion

 # prefer var s = o as string; if (s != null) {...}
 csharp_style_pattern_matching_over_as_with_null_check = false:suggestion

Inlined Variable Declarations


 [*.{cs}]
 # prefer if (int.TryParse(value, out int i) {...}
 csharp_style_inlined_variable_declaration = true:suggestion

 # prefer int i; if (int.TryParse(value, out i) {...}
 csharp_style_inlined_variable_declaration = false:suggestion

Code Block

"true" means use curly braces even around single-line blocks.

"false" means don't use curly braces if the compiler does not require them.

"when_multiline" means use curly braces around multi-line blocks.


 [*.{cs}]
 csharp_prefer_braces = true:suggestion
 csharp_prefer_braces = false:suggestion
 csharp_prefer_braces = when_multiline:suggestion

Unused Value


 [*.{cs}]
 # prefer _ = System.Convert.ToInt32("35");
 csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion

 # prefer var unused = Convert.ToInt32("35");
 csharp_style_unused_value_expression_statement_preference = unused_local_variable:suggestion


 [*.{cs}]
 # prefer _ = wordCount.TryGetValue(searchWord, out var count);
 csharp_style_unused_value_assignment_preference = discard_variable:suggestion

 # prefer var unused = wordCount.TryGetValue(searchWord, out var count);
 csharp_style_unused_value_assignment_preference = unused_local_variable:suggestion

Index And Range


 [*.{cs}]
 # prefer var index = names[^1];
 csharp_style_prefer_index_operator = true:suggestion

 # prefer var index = names[names.Length - 1];
 csharp_style_prefer_index_operator = false:suggestion


 [*.{cs}]
 # prefer var sub = sentence[0..^4];
 csharp_style_prefer_range_operator = true:suggestion

 # prefer var sub = sentence.Substring(0, sentence.Length - 4);
 csharp_style_prefer_range_operator = false:suggestion

Misc


 [*.{cs}]
 # prefer var (name, age) = GetPersonTuple(); (int x, int y) = GetPointTuple();
 csharp_style_deconstructed_variable_declaration = true:suggestion

 # prefer var person = GetPersonTuple(); (int x, int y) point = GetPointTuple();
 csharp_style_deconstructed_variable_declaration = false:suggestion


 [*.{cs}]
 # prefer int fibonacci(int n) { return n <= 1 ? 1 : fibonacci(n-1) + fibonacci(n-2); }
 csharp_style_pattern_local_over_anonymous_function = true:suggestion

 # prefer Func<int, int> fibonacci = null; fibonacci = (int n) => { return n <= 1 ? 1 : fibonacci(n - 1) + fibonacci(n - 2); };
 csharp_style_pattern_local_over_anonymous_function = false:suggestion

"outside_namespace" means using statements should be placed outside the namespace.
"inside_namespace" means using statements should be placed inside the namespace.

 [*.{cs}]
 csharp_using_directive_placement = outside_namespace:suggestion
 csharp_using_directive_placement = inside_namespace:suggestion

"true" means local functions should be explicitly declared static.

 [*.{cs}]
 csharp_prefer_static_local_function = true:suggestion
 csharp_prefer_static_local_function = false:suggestion


 [*.{cs}]
 # prefer using var a = b;
 csharp_prefer_simple_using_statement = true:suggestion

 # prefer using (var a = b) { }
 csharp_prefer_simple_using_statement = false:suggestion


 [*.{cs}]
 # prefer return x switch { 1 => 1 * 1, 2 => 2 * 2, _ => 0, };
 csharp_style_prefer_switch_expression = true:suggestion

 # prefer switch (x) { case 1: return 1 * 1; case 2: return 2 * 2; default: return 0; }
 csharp_style_prefer_switch_expression = false:suggestion

.Net Formatting Keys

Key-Value pairs recognised by .Net IDEs.

[documentation]

Organize Using Directives

"true" means sort System.* directives alphabetically and place above all others.

 [*.{cs,vb}]
 dotnet_sort_system_directives_first = true
 dotnet_sort_system_directives_first = false

"true" means insert a blank line between groups of using directives, based on their root namespace.

 [*.{cs,vb}]
 dotnet_separate_import_directive_groups = true
 dotnet_separate_import_directive_groups = false

New Line

When should an opening brace { be placed on a new line? Specify "all", "none", or a specific list of elements that the rule applies to.

 [*.cs]
 csharp_new_line_before_open_brace = all
 csharp_new_line_before_open_brace = none
 csharp_new_line_before_open_brace = accessors, anonymous_methods, anonymous_types, control_blocks, events, indexers, lambdas, local_functions, methods, object_collection_array_initializers, properties, types

"true" means these statements should start on a new line.

 [*.cs]
 csharp_new_line_before_else = true
 csharp_new_line_before_catch = true
 csharp_new_line_before_finally = true
 csharp_new_line_before_members_in_object_initializers = true
 csharp_new_line_before_members_in_anonymous_types = true
 csharp_new_line_between_query_expression_clauses = true

Indentation

"true" means these statements should be indented extra.

 [*.cs]
 csharp_indent_case_contents = true
 csharp_indent_switch_labels = true
 csharp_indent_labels = true
 csharp_indent_block_contents = true
 csharp_indent_braces = true
 csharp_indent_case_contents_when_block = true

Spacing

"true" means spaces should be inserted.

 [*.cs]
 csharp_space_after_cast = true
 csharp_space_after_keywords_in_control_flow_statements = true
 csharp_space_between_parentheses = control_flow_statements, type_casts
 csharp_space_before_colon_in_inheritance_clause = true
 csharp_space_after_colon_in_inheritance_clause = true
 csharp_space_around_binary_operators = before_and_after
 csharp_space_between_method_declaration_parameter_list_parentheses = true
 csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
 csharp_space_between_method_declaration_name_and_open_parenthesis = false
 csharp_space_between_method_call_parameter_list_parentheses = true
 csharp_space_between_method_call_empty_parameter_list_parentheses = false
 csharp_space_between_method_call_name_and_opening_parenthesis = false
 csharp_space_after_comma = true
 csharp_space_before_comma = false
 csharp_space_after_dot = false
 csharp_space_before_dot = false
 csharp_space_after_semicolon_in_for_statement = true
 csharp_space_before_semicolon_in_for_statement = false
 csharp_space_around_declaration_statements = false
 csharp_space_before_open_square_brackets = false
 csharp_space_between_empty_square_brackets = false
 csharp_space_between_square_brackets = false

Wrap

"true" means if multiple statements are on one line, keep it that way.
Ex: int i = 0; string name = "John";

 [*.cs]
 csharp_preserve_single_line_statements = true
 csharp_preserve_single_line_statements = false

"true" means if multiple statements are on one line in a block, keep it that way.
Ex: public int Foo { get; set; }

 [*.cs]
 csharp_preserve_single_line_blocks = true
 csharp_preserve_single_line_blocks = false






.Net Naming Convention Keys

Key-Value pairs recognised by .Net IDEs.

[documentation]

(VS 2019)
The order of these rules does not matter (assuming them don't directly overwrite each other).
They will be auto-sorted from most-general to most-specific.

Key-Value Format

A rule may require several key-value pairs to fully define, so the parse supports naming a group of pairs.

Generic example:

 # define a rule group
 dotnet_naming_rule.<rule_title>.symbols = <symbol_title>
 
 # specify the rules for a group
 dotnet_nameing_symbols.<symbol_title>.applicable_kinds = values

Specific example:

 [*.{cs,vb}]
 # this is all one rule group "public_members_must_be_capitalized"
 dotnet_naming_rule.public_members_must_be_capitalized.symbols   = public_symbols
 dotnet_naming_symbols.public_symbols.applicable_kinds           = property,method,field,event,delegate
 dotnet_naming_symbols.public_symbols.applicable_accessibilities = public
 dotnet_naming_symbols.public_symbols.required_modifiers         = readonly
 
 dotnet_naming_rule.public_members_must_be_capitalized.style    = first_word_upper_case_style
 dotnet_naming_style.first_word_upper_case_style.capitalization = first_word_upper
 
 dotnet_naming_rule.public_members_must_be_capitalized.severity = suggestion

Applicable Symbols

List which kinds of symbols your rule applies to.


 # specify all symbols
 dotnet_naming_symbols.<my_symbol_title>.applicable_kinds = *

 # specify a list of symbols
 dotnet_naming_symbols.<my_symbol_title>.applicable_kinds = namespace, class, struct, interface, enum, property, method, field, event, delegate, parameter, type_parameter, local, local_function

Accessibility Level

List which accessibility levels your rule applies to.


 # specify all accessibility levels
 dotnet_naming_symbols.<my_symbol_title>.applicable_accessibilities = *

 # specify a list of accessibility levels
 dotnet_naming_symbols.<my_symbol_title>.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected, local
"local" means "defined inside a method", such as local functions and local variables.

Modifiers

(optional - default is to match any modifiers)
List which modifiers of symbols your rule applies to.
Your rule will only apply to elements that have all the modifiers you specify.


 # specify a list of modifiers
 dotnet_naming_symbols.<my_symbol_title>.required_modifiers = abstract, async, const, readonly, static
"static" rules also apply to const elements because const is implicitly static. This can be overriden with a specific "const" rule.

Style

Specify the naming convention for the elements you've selected.

 dotnet_naming_rule.<my_rule_title>.style = <my_style_title>

You must specify a capitalization style for your rule, otherwise the entire rule might be ignored.


 # requires prefix
 dotnet_naming_style.<my_style_title>.required_prefix = my_prefix

 # requires suffix
 dotnet_naming_style.<my_style_title>.required_suffix = my_suffix

 # requires separator
 dotnet_naming_style.<my_style_title>.word_separator = my_char

 # requires capitalization
 dotnet_naming_style.<my_style_title>.capitalization = pascel_case
 dotnet_naming_style.<my_style_title>.capitalization = camel_case
 dotnet_naming_style.<my_style_title>.capitalization = first_word_upper
 dotnet_naming_style.<my_style_title>.capitalization = all_upper
 dotnet_naming_style.<my_style_title>.capitalization = all_lower

Severity

error - violation causes compiler error (this does not stop a build)

warning - violation causes compiler warning

suggestion - violation causes a suggestion (such as three gray dots under the code)

silent - violation causes nothing, but suggestion appears in the Refactorings menu, and auto-generated code uses this style
aka refactoring

none - violation causes nothing, but auto-generated code uses this style


 dotnet_naming_rule.<my_rule_title>.severity = error