Configure Naming Styles and Rules in Visual Studio and also at the solution/project level with an .editorconfig file

When it comes to naming fields in classes, there are three types of .NET developers (The truth is there are even more, but let’s focus on the three that I see most often). :-)

Number one – a pure camelCase name

These developers create fields that are using camelCasing, like the firstName field that you see in the code snippet below. Using camelCasing means that the name starts with a lowercase character and it can use uppercase characters in the name to start new words. To assign a constructor parameter with the same name, you have to use the this keyword like you see it in the code snippet below, because that’s the only way to distinguish the field from the parameter in the constructor, as both have the same name:

public class Person
{
  private string firstName;

  public Person(string firstName)
  {
    this.firstName = firstName;
  }
}

Number two – prefixing fields with an underscore

The fieldname is the same as with the previous approach, but with a leading underscore. This means the this keyword is not required in the constructor to assign the parameter to the field, as parameter and field have different names.

public class Person
{
  private string _firstName;

  public Person(string firstName)
  {
    _firstName = firstName;
  }
}

Number three – prefixing fields with an m_

Same approach as number two, but with a leading m, which stands for member (there are some developers who use a leading s instead of the m for static fields):

public class Person
{
  private string m_firstName;

  public Person(string firstName)
  {
    m_firstName = firstName;
  }
}

What kind of developer are you? I’m number two. But let’s be clear, it’s personal preference, no approach is better than the other. I like approach number two better than approach number one, as I can see immediately from the variable name that it’s a field and not a local variable or a parameter, and it’s less verbose than approach number three with the additional m in the prefix. :)

Create and Assign Fields with Visual Studio

In Visual Studio you can create and assign fields automatically from constructor parameters. Let’s say you have created the following Person class with a constructor that has a firstName parameter:

public class Person
{
  public Person(string firstName)
  {
  }
}

Now you want to assign the firstName parameter to a field of that class. To do that, you put the cursor on the firstName parameter and then you press CTRL+. to get suggestions from Visual Studio. The menu that you see in the screenshot below will pop up. I have already selected the entry Create and assign field ‘firstName’.

As you can see in the screenshot above, by default, Visual Studio uses the number one approach to create and assign the constructor parameter to a field that uses camelCasing, without a leading underscore or a leading m with an underscore. But you can adjust your preferred option. My preferred approach is number two, the field with the leading underscore. Let’s set this up in Visual Studio.

Configure Visual Studio to Use Your Preference

In Visual Studio, go to Tools->Options, and in the Options Window navigate to Text Editor – C# – Code Style – Naming as you see it in the screenshot below:

There you can see a few rules of Visual Studio. Click on the Manage naming styles button. This opens up this little Window:

There you click on the green plus to add a new naming style. The window that you see below pops up. First, enter as a naming style title the value _camelCase (It’s free text, you can enter whatever you want here, this is just used to reference your style). Next, enter an underscore as a required prefix, and finally, select camel Case Name as Capitalization. That’s it. At the bottom you see a sample identifier. It looks as expected. Click OK to close this dialog.

Now you have that new _camelCase style available, as you can see in the dialog below. Now click again OK in this dialog, and you’re back in Visual Studio’s Options Dialog.

As the new naming style is now available, you can create a rule for fields that uses this new naming style.

In the Options Dialog, click on the green plus that you see in the screenshot below at the bottom:

Clicking on the green plus adds a new rule there. Select like you see it in the screenshot below as a specification Private or Internal Field, as a Required Style _camelCase (the style that you have created in the previous steps), and as Severity Suggestion.

After you have added the new rule, click OK to close Visual Studio’s Options Dialog.

Now go back to your Person class and put the cursor on the firstName constructor parameter. Press again CTRL+. to get the suggestions from Visual Studio. And voilà, as you can see in the screenshot below, now Visual Studio suggests you to create a field with the name _firstName. Wonderful.

Also when you have an already existing field that doesn’t match the rule, Visual Studio will show a few dots under that field name to tell you “Hey, look at that field, I have some suggestions for you”:

When you put the cursor on the field that doesn’t match the rule and when you then press CTRL+., Visual Studio suggests you to rename the field, so that it has a leading underscore, exactly like we have configured it in the Options:

The rules that you configure in Visual Studio are the default rules. They can be overwritten by rules that come with a solution or with a project. Makes sense, right. If you work on a project, you want that all team members use the same rules. You do NOT want that everyone uses their own individual naming rules when they work on the same project.

Provide Naming Rules with Your Solution or Project

In your Visual Studio instance, you can configure the default rules in the options. But a solution or a project can override these rules, so that everyone who works on the solution/project is using the same rules, no matter what they have configured in Visual Studio.

To configure these rules, you use an .editorconfig file. Let’s create one at the solution level. To do this, right-click the solution in the solution explorer of Visual Studio and select from the context menu Add – New Item…, then you search in the Add New Item dialog for editorconfig like you see it in the screenshot below:

The editorconfig File (.NET) template is selected in the screenshot above, and I give the file the name editorConfig. Let’s add this one to the solution by clicking the Add button. Now the solution has the .editorconfig file included (Sorry for the solution name, I thought ConsoleApp297 is quite a cool name, but I have to admit, it was not my idea, but Visual Studio’s idea).

When you open that file, you’ll see a lot of default rules there. I added below the complete file content, so that you can look through it without doing all the steps on your own while reading this post:

# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
###############################
# Core EditorConfig Options   #
###############################
# All files
[*]
indent_style = space
# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 4
insert_final_newline = true
charset = utf-8-bom
###############################
# .NET Coding Conventions     #
###############################
[*.{cs,vb}]
# Organize usings
dotnet_sort_system_directives_first = true
# this. preferences
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_property = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_event = false:silent
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
dotnet_style_readonly_field = true:suggestion
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
###############################
# Naming Conventions          #
###############################
# Style Definitions
dotnet_naming_style.pascal_case_style.capitalization             = pascal_case
# Use PascalCase for constant fields  
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols  = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style    = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds            = field
dotnet_naming_symbols.constant_fields.applicable_accessibilities  = *
dotnet_naming_symbols.constant_fields.required_modifiers          = const
###############################
# C# Coding Conventions       #
###############################
[*.cs]
# var preferences
csharp_style_var_for_built_in_types = true:silent
csharp_style_var_when_type_is_apparent = true:silent
csharp_style_var_elsewhere = true:silent
# Expression-bodied members
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:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
# Null-checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
# Expression-level preferences
csharp_prefer_braces = true:silent
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
###############################
# C# Formatting Rules         #
###############################
# New line preferences
csharp_new_line_before_open_brace = all
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 preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
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_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true
###############################
# VB Coding Conventions       #
###############################
[*.vb]
# Modifier preferences
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

Now, let’s try the following: Let’s try to enforce approach number three (m_ prefix for private fields) for this solution with the .editorConfig file. To do that, I add the following to the .editorConfig file. As you can see, first I define the style with the m_ prefix, then a symbol that defines the target for our rule, which are private fields, and finally the rule itself that uses the style and the symbol

# Define the _camel_case_style
dotnet_naming_style.m_camel_case_Style.capitalization = camel_case
dotnet_naming_style.m_camel_case_Style.required_prefix = m_

# Define the symbol private_fields that is like the target for the rule
dotnet_naming_symbols.private_fields.applicable_kinds            = field
dotnet_naming_symbols.private_fields.applicable_accessibilities  = private

# Define the private_internal_fiels_should_use_m_underscore rule for private fields
dotnet_naming_rule.private_internal_fiels_should_use_m_underscore.severity = suggestion 
dotnet_naming_rule.private_internal_fiels_should_use_m_underscore.style = m_camel_case_Style
dotnet_naming_rule.private_internal_fiels_should_use_m_underscore.symbols = private_fields

Now, let’s place again the cursor on the firstName constructor parameter of the Person class and let’s press CTRL+. to get the suggestions from Visual Studio. As you can see below, I get now the m_firstName suggestion that is configured in the .editorconfig file.

In a solution/project without .editorconfig file I get again the _firstName suggestion with the m prefix like it is configured in the options of my Visual Studio instance.

Generate an .editorConfig file from Your Settings

Instead of manually adding naming styles and rules to an .editorconfig file like we did it in the previous section of this blog post, you can also auto-generate that .editorconfig file from the settings that you have created in the options of your Visual Studio instance, which might be an easier approach. In the Options Window under Text Editor – C# – Code Style – General you find a button that is called Generate .editorconfig file from settings, you see this button in the screenshot below. All you have to do is to click on that button to generate an .editorconfig file with all the code styles of your Visual Studio instance. You can save the generated .editorconfig file in your solution folder or in a specific project folder.

Summary

As you learned in this blog post, Visual Studio is a super flexible editor. You can configure your preferences in the options dialog and you can enforce these preferences for projects and solutions by providing an .editorconfig file.

I hope this helps you to understand different suggestions for different projects or for different Visual Studio installations. When you watch a demo or a presentation and you see different suggestions than in your Visual Studio installation, it’s either because of local settings configured in the options or because of an .editorconfig file.

Thanks for reading,
Thomas

Share this post

Comments (5)

  • Tom Reply

    This is a very useful blogpost. Thank you for writing this!

    September 15, 2021 at 8:19 pm
  • Melvyn Shepherd Reply

    Hi Thomas

    I am using the latest version of Visual Studio 2022 Enterprise Edition and I am having difficulty in prefixing fields with an underscore.

    I followed your instructions but when I do the Ctrl + . I get the option ‘Create and assign field ‘firstName’
    The underscore is missing ?

    Can you give me any advice on what may be causing this.
    I have tried closing and restarting Visual Studio, but this didn’t change anything.

    Kind Regards
    Melvyn Shepherd

    February 18, 2023 at 2:49 pm
    • Thomas Claudius Huber Reply

      Hi Melvyn, do you have a screenshot or can you describe what you adjusted already? The behaviour that you mention is the default behavior of Visual Studio.

      February 23, 2023 at 11:13 pm
      • Melvyn Shepherd Reply

        Hi Thomas

        Thaks for your response, but with trial and error I have resolved my problem.
        Not sure what was wrong in the first place, so I uninstalled and reinstalled Visual Studio 2022, again!
        It then started working. ok.

        February 24, 2023 at 11:23 am
        • Thomas Claudius Huber Reply

          Hi Melvyn,

          Ok, sounds great. Happy to read it’s working now for you.

          Happy coding,
          Thomas

          February 24, 2023 at 12:26 pm

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.