BLogic Systems

Back-end Coding Conventions

Last updated on 

C# Coding Conventions

This document outlines commonly accepted coding conventions for C# to promote consistency and readability in codebases.


Table of Contents


Naming Conventions

Item Convention Example
Class names PascalCase CustomerOrder
Interface names PascalCase, prefix I IRepository
Method names PascalCase CalculateTotal()
Property names PascalCase OrderAmount
Local variable names camelCase totalAmount
Parameter names camelCase string customerName
Constant PascalCase MAX_COUNTING_NUMBER
Private fields _camelCase _logger
Enum types and values PascalCase OrderStatus.Pending

Layout and Formatting

  • Place each statement on a new line.

Bracing

  • Use K&R style braces (Allman style is also acceptable if consistent).
if (condition)
{
    DoSomething();
}
else
{
    DoSomethingElse();
}

Commenting

  • Use XML documentation for public APIs
  • Use // for inline or single-line comments.
  • Avoid redundant comments that state the obvious.
         /// <summary>
        /// Update an item using a patch request
        /// </summary>
        /// <remarks>
        /// **Details:**
        /// - Partially updates an item for the specified store.
        /// </remarks>
        /// <param name="storeID">Store ID</param>
        /// <param name="id">Item ID</param>
        /// <param name="request">Patch request for item</param>
        /// <returns>The updated item with details</returns>
        [ProducesResponseType(typeof(BaseResponse<ItemWithDetailsQueryDTO>), 200)]
        [HttpPatch("{storeID}/{id}")]
        public async Task<IActionResult> UpdateItem(string storeID, Guid id, [FromBody] JsonPatchDocument<ItemUpdateRequest> request)
        {
            var dto = _mapper.Map<JsonPatchDocument<ItemWithDetailsQueryDTO>>(request);
            var response = await _itemCommandService.UpdateItem(storeID, id, dto);
            return Ok(new BaseResponse<ItemWithDetailsQueryDTO>(response));
        }

Framework DI

  • Use ILogger via DI.
  • With DI service mark it with private and readonly
     private readonly ILogger<MyService> _logger;
  • Using primary contructor if you can
    public class ItemsController(
        IItemCommandService itemCommandService,
        IItemQueryService itemQueryService,
        IMapper mapper) : ControllerBase
    {
        private readonly IItemCommandService _itemCommandService = itemCommandService;
        private readonly IItemQueryService _itemQueryService = itemQueryService;
        private readonly IMapper _mapper = mapper;

Language Usage

  • Use var when the type is obvious or repeated on the right-hand side:
var stream = new FileStream("file.txt", FileMode.Open);
  • Prefer string interpolation over concatenation:
$"Hello, {name}!"
  • Use expression-bodied members for simple properties and methods:
public int Square(int x) => x * x;
  • Use using statements or using declarations for disposable resources.
using var stream = new FileStream("file.txt", FileMode.Open);
  • Use the Async suffix** for all asynchronous methods
public async Task SaveChangesAsync()
  • Use verbatim and interpolation string if that is multiple line and complicated string
var query = @"
                	SELECT 
                    CASE 
                        WHEN MIN(r.KitchenIDs) = MAX(r.KitchenIDs) THEN MIN(r.KitchenIDs) 
                        ELSE NULL 
                    END AS KitchentIDs
                    
                    FROM (
                        SELECT i.ItemID, STRING_AGG(k.KitchenID , ',') WITHIN GROUP (ORDER BY k.KitchenID) AS KitchenIDs  FROM pos.Items i
                        LEFT JOIN pos.ItemKitchenDetails AS k
                        ON i.ItemID = k.ItemID AND k.StoreID = @StoreID AND k.IsDeleted = 0
                        WHERE i.StoreID = @StoreID AND i.DeptDeptID = @ItemCategoryID AND i.IsDeleted = 0
                        GROUP BY i.ItemID
                    ) AS r
            ";