Skip to main content

.NET Coding Conventions

Introduction

Coding conventions are a set of guidelines for a specific programming language that recommend programming style, practices, and methods. Following established coding conventions makes your code more readable, easier to maintain, and more consistent. In the .NET ecosystem, adhering to consistent coding conventions helps teams collaborate effectively and ensures that your code can be easily understood by other developers.

In this guide, we'll explore the standard coding conventions for .NET languages (primarily focusing on C#), understand why they matter, and learn how to apply them in your projects.

Why Coding Conventions Matter

Before diving into specific conventions, let's understand why they're important:

  1. Readability - Consistent code style makes reading code easier
  2. Maintainability - Following conventions makes code maintenance simpler
  3. Collaboration - Standardized code helps teams work together effectively
  4. Onboarding - New team members can understand code faster
  5. Error Prevention - Many conventions help prevent common coding mistakes

Naming Conventions

Pascal Case and Camel Case

.NET uses two primary casing styles:

  1. PascalCase: First letter of each word is capitalized (e.g., CalculateTax)
  2. camelCase: First letter is lowercase, then first letter of each subsequent word is capitalized (e.g., calculatedAmount)

When to Use Each Case Style

ElementConventionExample
Classes, RecordsPascalCasepublic class Customer {}
InterfacesPascalCase with 'I' prefixpublic interface IDisposable {}
MethodsPascalCasepublic void SaveChanges() {}
PropertiesPascalCasepublic string FirstName { get; set; }
Fields (private)camelCase with underscore prefixprivate string _firstName;
ParameterscamelCasepublic void Process(string firstName) {}
Local variablescamelCasestring fullName = firstName + lastName;
ConstantsPascalCasepublic const string DefaultName = "Unknown";

Example of Properly Named Code

csharp
public class CustomerService : IDisposable
{
private readonly DbContext _context;
private const int MaxRetryAttempts = 3;

public CustomerService(DbContext context)
{
_context = context;
}

public Customer GetCustomerById(int customerId)
{
string cacheKey = $"customer_{customerId}";
return _context.Customers.Find(customerId);
}

public void Dispose()
{
_context.Dispose();
}
}

File Organization Conventions

File Structure

  • One class per file (with exceptions for small, related classes)
  • File name should match the primary class name (e.g., Customer.cs contains the Customer class)
  • Organize files in directories that follow your namespace structure

Namespace and Using Directives

csharp
// System namespaces first
using System;
using System.Collections.Generic;

// Third-party libraries next
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;

// Your application namespaces last
using YourCompany.YourProduct.Models;
using YourCompany.YourProduct.Services;

namespace YourCompany.YourProduct.Controllers
{
public class CustomerController
{
// Class implementation
}
}

Code Layout Conventions

Indentation and Spacing

  • Use 4 spaces for indentation (not tabs)
  • Add a space after keywords like if, for, while, etc.
  • Add a space before and after operators (+, -, =, etc.)
  • Add a space after commas in method arguments
csharp
// Good
if (isActive)
{
int sum = value1 + value2;
DoSomething(sum, value3);
}

// Bad
if(isActive){
int sum=value1+value2;
DoSomething(sum,value3);
}

Braces

.NET typically uses the "Allman style" for braces, where opening braces are on a new line:

csharp
// Recommended bracing style
public void ProcessOrder(Order order)
{
if (order == null)
{
throw new ArgumentNullException(nameof(order));
}

foreach (var item in order.Items)
{
ProcessItem(item);
}
}

Exception: You can put the opening brace on the same line for very short single-line blocks:

csharp
// Acceptable for very short blocks
if (order == null) { throw new ArgumentNullException(nameof(order)); }

Line Length and Wrapping

Keep lines reasonably short (around 80-120 characters) and use consistent wrapping:

csharp
// Long method call with appropriate wrapping
var result = LongMethodNameWithManyParameters(
firstParameter,
secondParameter,
thirdParameter,
forthParameter);

Language-Specific Conventions

C# Specific Conventions

Use Properties Instead of Public Fields

csharp
// Good
public string Name { get; set; }

// Bad
public string Name;

Use Object Initializers

csharp
// Good
var customer = new Customer
{
FirstName = "John",
LastName = "Doe",
Age = 30
};

// Less preferred
var customer = new Customer();
customer.FirstName = "John";
customer.LastName = "Doe";
customer.Age = 30;

Use String Interpolation

csharp
// Good
string greeting = $"Hello, {firstName} {lastName}!";

// Less preferred
string greeting = "Hello, " + firstName + " " + lastName + "!";

Use var When Appropriate

csharp
// Good - type is obvious from right side
var customers = new List<Customer>();

// Good - type is obvious from method name
var customer = GetCustomer(id);

// Avoid when type is not obvious
var result = GetData(); // What type is result?

Use Expression-Bodied Members

csharp
// Good for simple methods
public string GetFullName() => $"{FirstName} {LastName}";

// Traditional equivalent
public string GetFullName()
{
return $"{FirstName} {LastName}";
}

Documentation Conventions

XML Documentation

Use XML comments to document public members:

csharp
/// <summary>
/// Calculates the total price including tax.
/// </summary>
/// <param name="price">The base price before tax.</param>
/// <param name="taxRate">The tax rate as a decimal (e.g. 0.07 for 7%).</param>
/// <returns>The total price including tax.</returns>
/// <exception cref="ArgumentException">Thrown when price is negative.</exception>
public decimal CalculateTotalPrice(decimal price, decimal taxRate)
{
if (price < 0)
{
throw new ArgumentException("Price cannot be negative", nameof(price));
}

return price * (1 + taxRate);
}

Error Handling Conventions

Validate Parameters

Use guard clauses at the beginning of methods:

csharp
public void ProcessOrder(Order order, Customer customer)
{
if (order == null)
throw new ArgumentNullException(nameof(order));

if (customer == null)
throw new ArgumentNullException(nameof(customer));

// Process the order...
}

Exception Handling

csharp
public void SaveData(Data data)
{
try
{
_repository.Save(data);
}
catch (DbException ex)
{
_logger.LogError(ex, "Database error occurred while saving data");
throw new DataAccessException("Failed to save data", ex);
}
}

Practical Example: A Complete Class Following Conventions

Let's put all these conventions together in a complete class:

csharp
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;

namespace OnlineStore.Services
{
/// <summary>
/// Provides shopping cart functionality for the online store.
/// </summary>
public class ShoppingCartService : IShoppingCartService
{
private readonly IProductRepository _productRepository;
private readonly ILogger<ShoppingCartService> _logger;
private readonly List<CartItem> _items = new List<CartItem>();

private const decimal DefaultTaxRate = 0.07m;

public ShoppingCartService(
IProductRepository productRepository,
ILogger<ShoppingCartService> logger)
{
_productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

public IReadOnlyList<CartItem> Items => _items.AsReadOnly();

public int ItemCount => _items.Sum(item => item.Quantity);

/// <summary>
/// Adds a product to the shopping cart.
/// </summary>
/// <param name="productId">The ID of the product.</param>
/// <param name="quantity">The quantity to add.</param>
/// <returns>True if the product was added successfully; otherwise, false.</returns>
public bool AddItem(int productId, int quantity)
{
if (quantity <= 0)
{
_logger.LogWarning("Attempted to add item with invalid quantity: {Quantity}", quantity);
return false;
}

try
{
var product = _productRepository.GetById(productId);
if (product == null)
{
_logger.LogWarning("Product not found: {ProductId}", productId);
return false;
}

var existingItem = _items.FirstOrDefault(i => i.ProductId == productId);
if (existingItem != null)
{
existingItem.Quantity += quantity;
}
else
{
_items.Add(new CartItem
{
ProductId = productId,
ProductName = product.Name,
UnitPrice = product.Price,
Quantity = quantity
});
}

_logger.LogInformation(
"Added {Quantity} of product {ProductId} to cart. Total items: {TotalItems}",
quantity,
productId,
ItemCount);

return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding product {ProductId} to cart", productId);
return false;
}
}

public decimal CalculateTotal() =>
_items.Sum(item => item.UnitPrice * item.Quantity);

public decimal CalculateTotalWithTax(decimal taxRate = DefaultTaxRate) =>
CalculateTotal() * (1 + taxRate);
}

public class CartItem
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public decimal UnitPrice { get; set; }
public int Quantity { get; set; }
public decimal LineTotal => UnitPrice * Quantity;
}
}

Tools for Enforcing Conventions

Several tools can help you maintain coding conventions automatically:

  1. EditorConfig: Create an .editorconfig file to define and enforce coding styles across different editors.
  2. StyleCop: Analyzes C# code for style violations.
  3. ReSharper/Rider: JetBrains tools that include code style enforcement.
  4. .NET Analyzers: Built-in static code analyzers that can enforce code quality rules.

Here's a sample .editorconfig file for a .NET project:

# Top-most EditorConfig file
root = true

# All files
[*]
indent_style = space
indent_size = 4
end_of_line = crlf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

# C# files
[*.cs]
# 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

# Indentation preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_block_contents = true

# Space preferences
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_parentheses = false

Summary

Following consistent coding conventions in .NET:

  • Makes your code more readable and maintainable
  • Helps teams collaborate more effectively
  • Reduces the cognitive load when reading and understanding code
  • Prevents common programming errors
  • Makes code reviews more focused on substance rather than style

The conventions we covered include:

  • Naming conventions (PascalCase and camelCase)
  • File organization
  • Code layout and formatting
  • Language-specific best practices
  • Documentation standards
  • Error handling

Remember that while these conventions are widely accepted in the .NET community, the most important thing is consistency within your team or project. Many organizations customize these guidelines to fit their specific needs while maintaining the core principles of readability and maintainability.

Additional Resources

Exercises

  1. Review a piece of your own code and identify places where it doesn't follow the conventions outlined above. Refactor it to adhere to the conventions.

  2. Create an .editorconfig file for one of your projects to enforce consistent formatting.

  3. Take the following poorly formatted code and refactor it to follow .NET conventions:

csharp
class customer{
public string firstname;
public string lastname;
public int Age;
public List<order> orders=new List<order>();

public void addOrder(order o){orders.Add(o);}
public string getFullName(){return firstname+" "+lastname;}
public decimal calculateTotalSpent(){
decimal total=0;
foreach(var o in orders)total+=o.amount;
return total;
}
}
  1. Practice writing XML documentation comments for a class or method you've created.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)