GST C# Naming Convention Standards
This document defines the C# naming conventions for the GatherSystemTech team, based on Microsoft .NET naming guidelines with team-specific conventions.
1. Project Naming (.csproj)
1.1 Base Framework Projects
Format: GST.{Layer}.{Module}
| Layer | Format | Example |
|---|---|---|
| Core Abstractions | GST.Core.{Domain} | GST.Core.Abstractions, GST.Core.Common |
| Feature Plugins | GST.Plugin.{FeatureName} | GST.Plugin.UserManagement, GST.Plugin.AuditTrail |
| Protocol Plugins | GST.Plugin.{Protocol} | GST.Plugin.Modbus, GST.Plugin.S7 |
| UI Abstractions | GST.UI.{Framework} | GST.UI.Wpf, GST.UI.WinForms |
| Service Infrastructure | GST.ServiceInfrastructure.{Component} | GST.ServiceInfrastructure.Host |
| Tools | GST.Tools.{ToolName} | GST.Tools.LocalizationGenerator |
1.2 Application Layer Projects
General application format: GST.App.{ProjectName}
GST.App.ProcessVision # UI layer
GST.App.ProcessVision.Core # Business logic layer
Company-specific application format: {Company}.{ProjectName}
When an application needs to be published under a client/partner company brand, a company prefix is allowed:
Jope.SMB.Core # Jope SMB business logic
Jope.SMB.WPF # Jope SMB UI layer
Leyu.{ProjectName} # Leyu projects
Note: This rule applies to subcontracted projects where the software must display the client company name externally.
1.3 Test Projects
Format: {OriginalProject}.Tests
GST.Core.Common.Tests
GST.Plugin.UserManagement.Tests
Jope.SMB.Core.Tests
2. Namespaces
2.1 Format
Standard format: {ProjectName}.{Subdomain}
// Base framework
namespace GST.Core.Abstractions.Audit;
namespace GST.Plugin.UserManagement.Services;
namespace GST.Plugin.Modbus.Rtu;
// Application layer
namespace GST.App.ProcessVision.ViewModels;
namespace Jope.SMB.Core.Devices;
namespace Jope.SMB.WPF.Services;
2.2 Rules
- Maximum 4 levels deep
- Must correspond to folder structure
- Use file-scoped namespaces (C# 10+)
// ✅ Correct - File-scoped namespace
namespace GST.Core.Abstractions.Audit;
public interface IAuditService { }
// ❌ Avoid - Block-scoped namespace
namespace GST.Core.Abstractions.Audit
{
public interface IAuditService { }
}
3. File Naming
All files use PascalCase, named after the primary class/interface.
| Type | Format | Example |
|---|---|---|
| Interface | I{ConceptName}.cs | IUserService.cs, ICacheService.cs |
| Service | {Concept}Service.cs | UserService.cs, MemoryCacheService.cs |
| Repository | {Entity}Repository.cs | UserRepository.cs |
| Entity | {Concept}Entity.cs | UserEntity.cs, RoleEntity.cs |
| Request DTO | {Action}{Concept}Request.cs | CreateUserRequest.cs |
| Response DTO | {Concept}Response.cs | LoginResponse.cs |
| Exception | {Concept}Exception.cs | ModbusException.cs |
| Extension Methods | {TargetType}Extensions.cs | StringExtensions.cs |
| Helper Utilities | {Concept}Helper.cs | RetryHelper.cs |
| Options/Configuration | {Concept}Options.cs | AuthenticationOptions.cs |
| Factory | {Concept}Factory.cs | ControllerFactory.cs |
| Enum | {Concept}.cs (singular) | AlarmSeverity.cs |
| ViewModel | {Name}ViewModel.cs | MainViewModel.cs |
| Converter | {Name}Converter.cs | BoolToVisibilityConverter.cs |
3.1 Helper vs Extensions Distinction
| Type | Purpose | Example |
|---|---|---|
| Extensions | Extension methods (with this parameter) | StringExtensions.cs |
| Helper | Static utility methods (without this parameter) | RetryHelper.cs |
// Extensions - Extension methods
public static class StringExtensions
{
public static bool IsNullOrEmpty(this string value) => string.IsNullOrEmpty(value);
}
// Helper - Static utility methods
public static class RetryHelper
{
public static async Task<T> ExecuteWithRetryAsync<T>(Func<Task<T>> action, int maxRetries) { }
}
4. Class/Interface Naming
4.1 Naming Patterns
| Type | Format | Example |
|---|---|---|
| Interface | I{ConceptName} | IUserService, ICacheService |
| Abstract Class | {Concept}Base | ViewModelBase, PresenterBase |
| Service | {Concept}Service | UserService, RoleService |
| Repository | {Entity}Repository | UserRepository |
| Factory | {Concept}Factory | ControllerFactory |
| Controller (Device) | {DeviceName}Controller | TaieFcController |
| Manager | {Concept}Manager | AlarmManager |
| Builder | {Concept}Builder | CommandBuilder |
| Handler | {Concept}Handler | MessageHandler |
4.2 Service vs Manager vs Handler Distinction
| Type | Responsibility | Example |
|---|---|---|
| Service | Business logic (CRUD, validation, computation) | UserService, AuthenticationService |
| Manager | Resource management (lifecycle, state, pooling) | ConnectionManager, AlarmManager |
| Handler | Event/message handling (responds to specific events) | MessageHandler, ErrorHandler |
4.3 Access Modifiers
| Modifier | Purpose |
|---|---|
public interface | External contract |
public abstract class | Inheritable base class |
public sealed class | Non-inheritable public class |
internal class | Internal implementation (most common) |
internal sealed class | Internal non-inheritable |
5. Method Naming
5.1 Naming Patterns
| Operation | Format | Example |
|---|---|---|
| Get single | Get{Entity}[By{Key}]Async | GetUserByIdAsync |
| Get multiple | Get{Entities}Async | GetUsersAsync, GetAllRolesAsync |
| Create | Create{Entity}Async | CreateUserAsync |
| Update | Update{Entity}Async | UpdateUserAsync |
| Delete | Delete{Entity}Async | DeleteUserAsync |
| Validate | Validate{Concept}Async | ValidatePasswordAsync |
| Verify | Verify{Concept}Async | VerifyChainAsync |
| Check existence | {Entity}ExistsAsync | UserExistsAsync |
| Try operation | Try{Action} | TryParse, TryGetValue |
| Event handler | On{EventName} | OnConnected, OnError |
5.2 Async Method Rules
- All async methods must end with
Async - Must include a
CancellationTokenparameter
// ✅ Correct
public async Task<User> GetUserByIdAsync(
Guid id,
CancellationToken cancellationToken = default);
// ❌ Wrong - Missing Async suffix and CancellationToken
public async Task<User> GetUserById(Guid id);
6. Variable Naming
6.1 Naming Rules
| Type | Format | Example |
|---|---|---|
| Private field | _camelCase | _userRepository, _logger |
| Public property | PascalCase | Username, IsActive |
| Parameter | camelCase | userId, cancellationToken |
| Local variable | camelCase | user, result |
| Constant | PascalCase | MaxRetryCount, DefaultTimeout |
| Static readonly | PascalCase | Empty, Default |
6.2 Boolean Naming
Use Is/Has/Can/Should prefixes:
// ✅ Correct
public bool IsActive { get; set; }
public bool HasPermission { get; set; }
public bool CanExecute { get; set; }
public bool ShouldRetry { get; set; }
// ❌ Avoid
public bool Active { get; set; } // Unclear if verb or adjective
public bool Permission { get; set; } // Unclear what type it represents
7. Enum Naming
7.1 Regular Enums
Use singular names with PascalCase values:
public enum AlarmSeverity
{
Critical = 0,
High = 1,
Medium = 2,
Low = 3
}
public enum ChannelState
{
Disconnected = 0,
Connecting = 1,
Connected = 2,
Error = 3
}
7.2 Flags Enums
Use plural names:
[Flags]
public enum FilePermissions
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
All = Read | Write | Execute
}
8. Folder Structure
8.1 Base Project Structure
GST.Plugin.{FeatureName}/
├── Abstractions/ # Interface definitions
├── Models/ # Data models (Entity, DTO)
├── Services/ # Service implementations
├── Repositories/ # Data access
├── Extensions/ # Extension methods
├── Helpers/ # Utility helpers
├── Exceptions/ # Custom exceptions
└── Configuration/ # Configuration related
8.2 Application Layer Project Structure
{App}.WPF/ # UI layer
├── Controls/ # Custom controls
├── Converters/ # Value converters
├── Resources/ # Resource files
│ ├── Icons/
│ └── Localization/
├── Services/ # UI services
├── ViewModels/ # ViewModels
├── Views/ # Views (XAML)
└── Themes/ # Themes
{App}.Core/ # Business logic layer
├── Models/ # Domain models
├── Services/ # Business services
├── Repositories/ # Data access
└── {Domain}/ # Grouped by domain
├── Models/
└── Services/
9. XML Documentation Comments
9.1 Rules
- All
publicmembers must have XML comments - Write in English (to avoid encoding issues)
- Be concise and clear, avoid repeating the method name
9.2 Example
/// <summary>
/// Provides user management operations including CRUD and authentication.
/// </summary>
public interface IUserService
{
/// <summary>
/// Gets a user by their unique identifier.
/// </summary>
/// <param name="id">The unique identifier of the user.</param>
/// <param name="cancellationToken">A token to cancel the operation.</param>
/// <returns>The user if found; otherwise, null.</returns>
/// <exception cref="ArgumentException">Thrown when id is empty.</exception>
Task<User?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
}
10. Record Types
Used for immutable Data Transfer Objects (DTOs):
// Request DTO
public record CreateUserRequest
{
public required string Username { get; init; }
public required string Password { get; init; }
public string DisplayName { get; init; } = string.Empty;
}
// Response DTO
public record LoginResponse
{
public required string Token { get; init; }
public required DateTime ExpiresAt { get; init; }
}
// Result type
public record AuditChainVerificationResult
{
public required bool IsValid { get; init; }
public required int TotalEntriesVerified { get; init; }
public IReadOnlyList<string> Errors { get; init; } = [];
}
11. Prohibited Practices
11.1 Naming Prohibitions
// ❌ Prohibited - Hungarian notation
string strName;
int iCount;
bool bIsActive;
// ❌ Prohibited - Abbreviations (unless commonly accepted like Id, Url, Html)
string usrNm;
int cnt;
// ❌ Prohibited - Underscore-prefixed public members
public string _username;
// ❌ Prohibited - All caps (except for acronyms)
public const int MAXRETRYCOUNT = 3;
11.2 Commonly Accepted Abbreviations
| Abbreviation | Full Name |
|---|---|
| Id | Identifier |
| Url | Uniform Resource Locator |
| Html | HyperText Markup Language |
| Xml | Extensible Markup Language |
| Json | JavaScript Object Notation |
| Dto | Data Transfer Object |
| Io | Input/Output |
| Ui | User Interface |
| Api | Application Programming Interface |
12. Project Prefix Reference Table
| Prefix | Purpose | Example |
|---|---|---|
GST.* | Base framework | GST.Core.Common, GST.Plugin.Modbus |
GST.App.* | General applications | GST.App.ProcessVision |
Jope.* | Jope-specific applications | Jope.SMB.Core |
Leyu.* | Leyu-specific applications | Leyu.{ProjectName} |
{Company}.* | Other company-specific | Per client requirements |
13. Checklist
When creating new projects or during code review, verify the following:
Project Level
- Project name follows
GST.*or{Company}.*format - Test projects use
.Testssuffix - Uses file-scoped namespaces
File Level
- File name matches the primary class name
- Interface files use
Iprefix - Appropriate use of Entity/Request/Response suffixes
Class Level
- Interfaces use
Iprefix - Abstract classes use
Basesuffix - Service/Manager/Handler distinction is correct
Member Level
- Private fields use
_camelCase - Public properties use
PascalCase - Async methods use
Asyncsuffix - Boolean properties use
Is/Has/Can/Shouldprefix
Documentation
- All public members have XML comments
- Comments are in English
Version History
| Version | Date | Change Description |
|---|---|---|
| 1.0 | 2025-01-17 | Initial creation |