English
Français

Blog of Denis VOITURON

for a better .NET world

.NET Naming Conventions

Pascal case and Camel case

There are several naming conventions to consider when writing code. We use these two practices: PascalCasing or camelCasing.

  1. Pascal Case

    Use pascal casing (“PascalCasing”) when naming a namespace, class, record, or struct.

  2. Camel Case

    Use camel casing (“camelCasing”) when naming private or internal fields, and prefix them with _.

Example

public class DataService
{
    private IWorkerQueue _workerQueue;

    public bool IsValid;

    public event Action EventProcessing;

    public int Add(int first, int second)
    {
        return first + second;
    }
}

Examples:

Item Case Example
Namespace Pascal System.File.Directory
Class Pascal AppDomain
Class Exception Pascal WebException (suffix Exception)
Interface Pascal IDisposable (prefix I)
Event Pascal ValueChange
Enum Type Pascal ErrorLevel
Enum Value Pascal FatalError
Variable Private Camel _lastName (prefix _)
Variable Local Camel lastName
Read Only Pascal RedColor
Constant UPPER BLUE
Method Pascal ToString()
Property Pascal BackColor
Parameter Camel typeName



File organizations

Organize your files in separate folders to respect these rules:



Item naming

To avoid confusion and to write clean code, all items created must be defined:


For Boolean variables and properties, add the prefix Is or Has before the name.



Layout conventions

Good layout uses formatting to emphasize the structure of your code and to make the code easier to read:



Postfix asynchronous methods with Async

By convention, methods that return commonly awaitable types (for example, Task, Task<T>, ValueTask, ValueTask<T>) should have names that end with “Async”: AV1755 or VSTHRD200.

Example:

async Task DoSomethingAsync()
{
    await MyFirstMethodAsync();
    await MySecondMethodAsync();
}

bool DoSomethingElse()
{
    return false;
}

Eliding Async and Await

If it’s possible, it is more efficient to elide async and await. By not including these keywords, the compiler can skip generating the async state machine. This means that there are fewer compiler-generated types in your assembly, less pressure on the garbage collector, and fewer CPU instructions to execute.

We suggest:

Example:

Task DoSomethingAsync()
{
    return MyMethodAsync();
}

More:



Place members in a well-defined order

Maintaining a common order allows other team members to find their way in your code more easily. In general, a source file should be readable from top to bottom, as if reading a book, to prevent readers from having to browse up and down through the code file.

See AV2406

  1. Private fields and constants
  2. Public constants
  3. Public static read-only fields
  4. Factory methods
  5. Constructors and the finalizer
  6. Events
  7. Public and protected properties
  8. Other methods and private properties in calling order

Declare local functions at the bottom of their containing method bodies (after all executable code).

Do not use #region. Regions require extra work without increasing the quality or the readability of code. Instead they make code harder to view and refactor.



Variables



Commenting conventions



Using and namespace

To respect naming conventions used by other Microsoft Teams (.NET team, AspNetCore Team, …), we decided to use thse rules:

The last rule (IDE0161) solves the question asked this StackOverflow article.

using using Microsoft.AspNetCore.Components;
using System;

namespace MyNamespace;

public class Foo
{
}



If pattern

Prefer positive conditionals and method names: if (a > b) is better than if (a !<= b).

See https://www.codeproject.com/Articles/1073387/Robert-s-Rules-of-Coders-sharp-Avoid-Negative-Cond

a. Braces

Always use braces with if statement, including when you have only one line of code.

if (condition)
{
  DoSomething();
}
else
{
  DoSomethingOther();
}
if (condition)
{
   DoSomething();
   DoSomething();
   ...
} 
else if (condition) 
{
   DoSomethingOther();
   DoSomethingOther();
   ...
} 
else 
{
   DoSomethingOtherAgain();
   DoSomethingOtherAgain();
   ...
}

b. No Else Return

You can skip the else block if your if block always executes a return statement.

if (condition)
{
   return ReturnSomething();
}

return ReturnSomethingOther();

See https://www.samanthaming.com/tidbits/23-no-else-return

c. Guard pattern

The guard clause is a block of code that is at the begining of the function that returns early, and stop all execution(s),if the statment is met.

if (isSeparated)
{
   return null;
}

return ReturnSomething();

See https://refactoring.guru/replace-nested-conditional-with-guard-clauses



String data type

Use string interpolation to concatenate short strings, as shown in the following code.

string displayName = $"{nameList[n].LastName}, {nameList[n].FirstName}";

To append strings in loops, especially when you’re working with large amounts of text, use a StringBuilder object.

var phrase = "lalalalalalalalalalalalalalalalalalalalalalalalalalalalalala";
var manyPhrases = new StringBuilder();
for (var i = 0; i < 10000; i++)
{
    manyPhrases.Append(phrase);
}
Console.WriteLine($"tra{manyPhrases");



Exception handler

Don’t swallow errors by catching generic exceptions: see AV1210. Avoid swallowing errors by catching non-specific exceptions, such as Exception, SystemException, and so on, in application code. Only in top-level code, such as a last-chance exception handler, you should catch a non-specific exception for logging purposes and a graceful shutdown of the application.

If it’s possible, avoid to use try ... catch and prefer checking your data or your environment before to execute an action. For example, use File.Exists before to read a file, use myArray.Length before to read an item, use Int32.TryParse before to convert a string.

More detail in this article.



Operators allowed

C# provides a number of operators. Many of them are supported by the built-in types and allow you to perform basic operations with values of those types.

To keep a clean code, use only these operators.

Allowed

Denied



Data Convertion

Always use one of these method to convert an item from a datatype to another one:

Examples:

var a = Convert.ToString(myVariable);
var b = (string) myVariable;
var c = Convert.ToString(myVariable);
var d = $"{myVariable}"

⚠️ Never to use .ToString() to cast an object to a string

Convert.ToString() handles null, while ToString() doesn’t.



DateTime

To improve the quality of unit tests, prefer the use of a DateTimeProvider.

Always to use DateTimeProvider (and not DateTime) to allow UnitTest and date mocks.

int trimester = (DateTimeProvider.Today.Month - 1) / 3 + 1;

More details at: https://dvoituron.com/2020/01/22/UnitTest-DateTime



Static

Avoid static classes and static methods. See AV1008 With the exception of extension method containers, static classes very often lead to badly designed code. They are also very difficult, if not impossible, to test in isolation, unless you’re willing to use some very hacky tools.

Note: If you really need that static class, mark it as static so that the compiler can prevent instance members and instantiating your class. This relieves you of creating an explicit private constructor.

Languages

EnglishEnglish
FrenchFrançais

Follow me

Recent posts