C# Code Formatting and Development Conventions
Naming Conventions and Terminology
Pascal Case: Capitalize the first letter of the identifier and the first letter of each subsequent concatenated word. Use for identifiers with three or more characters. Example: PrimaryColor
Camel Case: The first letter of the identifier is lowercase, while the first letter of each subsequent concatenated word is capitalized. Example: primaryColor
Source File Structure
File names follow PascalCase convention. File extensions should be lowercase.
Begin each source file with a descriptive header comment block detailing its purpose.
/************************************************
// File Name: UserService.cs
// Description: Handles user authentication and profile management.
// Author: DevTeam
// Created: 2023-10-26
// Notes: Implements IUserService interface.
// Modified By: TeamLead
// Modified: 2023-11-05
// Modification: Added password reset functionality.
************************************************/
File descriptions should focus on overall functionality. Detailed class-level comments should be placed within the class definition. Multiple modifications on the same day should be grouped under a single modification note.
Code Formatting Guidelines
Line Width and Wrapping
Maintain a maximum line width of approximately 100 characters. Wrap lines at logical points, indenting continuation lines by one tab (4 spaces). Prefer breaking after a comma, before an operator.
Indentation
Use one tab (4 spaces) per indentation level. Avoid using actual tab characters in source files.
Spacing and Line Breaks
Use two blank lines to separate:
- Interface and class definitions.
- Enum and class definitions.
- Separate class definitions.
Use one blank line to separate: - Methods and properties.
- Variable declarations from executable statements within a method.
- Different logical sections within a method.
- A return statement from preceding code.
Insert a single space after keywords and before opening parentheses. Do not insert a space between a method name and its opening parenthesis. Separate multiple parameters with a comma followed by a space. Place spaces around binary operators (except the dot operator). Avoid spaces around unary operators, increment, and decrement operators. ### Brace Style
Place the opening brace { on a new line, aligned with the controlling statement. Align closing braces } with their correpsonding opening brace. Always use braces with if, while, do, and for statements, even for single-line bodies. Add a comment after a closing brace for complex nested blocks to indicate its scope.
Example of acceptable style:
if (isValid)
{
ProcessRequest();
}
Avoid inline brace placement:
if (isValid) { // Avoid this style
ProcessRequest();
}
Commenting Practices
Comments should explain the "why" and "what," not the obvious "how." Keep comments updated when modifying code. Use end-of-line comments for variable declarations and single-line comments elsewhere. Avoid visual clutter like rows of asterisks. Use whitespace to separate comments from code. Remove temporary or debug comments before release. If a section requires complex comments, consider refactoring the code for clarity. Write comments in complete sentences. Comment on non-obvious logic, error conditions, and workarounds.
Single-Line Comments
// Validate input before processing
if (userInput != null)
{
// Proceed with data extraction
ExtractData(userInput);
} // End of validation block
Multi-Line Comments
/* This algorithm calculates the weighted average
* based on user-provided coefficients. Ensure
* coefficients sum to 1.0 for accurate results.
*/
double result = CalculateWeightedAverage(data, weights);
XML Documentatino Comments
Use standard .NET XML documentation tags for public APIs.
/// <summary>
/// Validates user credentials against the database.
/// </summary>
/// <param name="username">The user's login identifier.</param>
/// <param name="passwordHash">The hashed password for verification.</param>
/// <returns>True if authentication succeeds; otherwise, false.</returns>
/// <exception cref="System.ArgumentException">Thrown when username is null or empty.</exception>
public bool AuthenticateUser(string username, string passwordHash)
{
// Implementation
}
Declaration and Naming Rules
Declare one variable per line. Initialize variables at the point of declaration. Place variable declarations at the beginning of a block, except in loop initializers. Avoid naming conflicts between variables in different scopes.
Class and Interface Naming: Use nouns or noun phrases. Do not use type prefixes or underscores. Interface names should start with a capital 'I'.
Method Naming: Use verbs or verb phrases. Boolean-returning methods should start with "Is".
Property Naming: Use nouns or noun phrases. Boolean-returning properties should start with "Is".
Field Naming: Avoid public fields. Use properties instead. Private and protected fields use camelCase. Consider prefixing private backing fields with an underscore.
Constant Naming: Use uppercase with underscores separating words: MAX_RETRY_COUNT.
Statement and Control Flow
Limit each line to a single statement. Always use braces with control flow statements, even for single-line bodies. Avoid embedded assignments within expressions. Prefer explicit type casting over implicit. Avoid type conversion where possible.
Return Statements: Omit parentheses unless they improve clarity.
return;
return CalculateTotal();
return (offset != 0 ? offset : defaultOffset);
Switch Statements: Place each case on a separate line. Order cases logically (e.g., alphabetically). Always include a default case. All non-empty case blocks must terminate with a break statement.
switch (statusCode)
{
case 200:
HandleSuccess();
break;
case 404:
HandleNotFound();
break;
default:
HandleError();
break;
}
Exception Handling: Use try-catch-finally blocks judiciously. Catch specific exception types.
try
{
ReadConfiguration();
}
catch (FileNotFoundException ex)
{
LogError("Config file missing", ex);
}
finally
{
CleanupResources();
}
Using Statements: Employ the using statement for deterministic disposal of IDisposable objects.
using (var streamReader = new StreamReader(filePath))
{
content = streamReader.ReadToEnd();
}
Avoid using the goto statement.
Performance and Best Practices
- Conduct thorough testing before deployment.
- Build Release configurations for production; disable debug mode in web applications.
- Use the
this.qualifier for member access within a class. - Qualify static member calls with the class name.
- Prefer the
asoperator for reference type conversions to avoid exceptions. - Avoid creating objects inside loops; instantiate in logical branches or use constants.
- Eliminate loops that execute only once.
- Cache intermediate calculation results to avoid redundant computations.
- Use
StringBuilderfor extensive string concatenation. - Initialize
StringBuilderwith an estimated capacity when known. - Prefer
String.Formator string interpolation over concatenation for formatted strings. - Minimize type conversions and boxing/unboxing operations.
- In MVC applications, avoid legacy Web Forms server controls.
- Use view templates or controlled string output for rendering.
- Favor client-side Ajax calls over full postbacks where appropriate.
- Note that float and double performance characteristics are context-dependent.
- Utilize bit-shifting and precomputation for performance optimizations.
- Eliminate redundant calculations and repeated method calls.
- Choose
Dictionary<TKey, TValue>overHashtablefor type safety and performance; be mindful of resizing overhead. - Manually release unmanaged resources; do not rely solely on garbage collection.
- Minimize database connection time and close connections promptly.
- Employ stored procedures to reduce network traffic and improve execution plans.
- Optimize SQL queries following database-specific guidelines.
- Configure server settings to match application requirements.
- Implement caching for data and page output where beneficial.
- Evaluate cache hit rates and choose appropriate cache expiration policies.
- Select the most suitable data access mechanism for the scenario.
- Use
DataReaderfor fast, forward-only data retrieval; be aware of connection lifetime implications. - Avoid COM component dependencies when possible.
- Use
Server.Transferfor server-side redirection to maintain URL consistency. - Tune thread pool settings for high-concurrency applications.
- Leverage garbage collection and automatic memory management appropriately.
- Consider pre-compilation for large web applications.
- Do not suppress exceptions; handle them meaningfully or allow them to propagate.
- Only catch exceptions you intend to handle.
- Disable ViewState for server controls when not required.
- Use
Page.IsPostBackto avoid unnecessary processing on initial load. - Disable Session state if not needed.
- Use reflection sparingly due to its performance cost.