---
tags: guides
---
# C# Coding guidelines
authors: **Nazarii Taran**, **Roman Makhnyk**
old page: https://hackmd.io/@kRVOe6MkQdSn1HsuDXuQAw/By9TzQeIN
## Naming
* Загальне правило для іменування сутностей - **PascalCase**.
* З маленької літери починаються (**camelCase**):
1. Локальні змінні;
2. Формальні параметри методу.
* Імена солюшенів, проектів, папок - **PascalCase**.
* Імена класів, структур, констант, властивостей, методів - **PascalCase**.
* Використовувати символ нижнього підкреслення (```_```) тільки в іменах полів (крім static readonly - до них правило таке ж як до констант).
* Імена інтерфейсів починаються з префіксу ```I```.
* Імена generic-параметрів починаються з префіксу ```T```.
* Не використовуйте надлишковий ```this```.
* Ніколи не вказуйте модифікатори доступу до членів інтерфейсів.
* Завжди вказуйте модифікатори доступу до інших членів коду.
### Приклади
:broken_heart:
```csharp=
namespace Project_Name
{
}
namespace projectName
{
}
public class userService
{
}
public class User_Service
{
}
public interface Editable
{
}
public interface editable
{
}
public class BadClassMemberNamingDemo
{
public const string DEFAULT_NAME = "No Name";
private int FieldName;
private int fieldName;
public void method()
{
}
public void method_name()
{
}
public void BadArgumentsNamingDemo(int FirstArgument, int Second_Argument)
{
}
public void BadGenericNamingDemo<Entity, otherEntity>()
{
}
public void BadLocalVariableNamingDemo()
{
int local_variable = 0;
}
}
```
:green_heart:
```csharp=
namespace ProjectName
{
}
namespace Extensions
{
}
public class UserService
{
}
public interface IEditable
{
}
public interface IUserService
{
}
public class GoodMemberNamingDemo
{
public const string DefaultName = "No Name";
private int _fieldName;
public int PropertyName { get; set; }
public void MethodName()
{
}
public void GoodArgumentsNamingDemo(int firstArgument, int secondArgument)
{
}
public void GoodGenericNamingDemo<TEntity>()
{
}
public void GoodLocalVariableNamingDemo()
{
int localVariable = 0;
}
}
```
## Class layout
* Члени класу мають бути відсортовані у такому порядку:
1. Поля;
2. Конструктори;
3. Властивості;
4. Індексатори;
5. Події;
6. Методи.
* Усередині кожної групи сортування по static\instance:
1. Константи;
2. Static члени;
3. None-static.
* Усередині кожної групи сортування по області видимості:
1. public;
2. protected;
3. private.
### Приклади
:broken_heart:
```csharp=
public class MyClass
{
public void Method1()
{
}
public int Property1 { get; set; }
private static int staticField = 0;
public MyClass()
{
}
private int field1;
public const string Const = "const";
protected Property2 { get; set; }
public static void Static1()
{
}
private void Method3()
{
}
private static void Static2()
{
}
public void Method2()
{
}
}
```
:green_heart:
```csharp=
public class MyClass
{
public const string Const = "const";
private static int staticField = 0;
private int field1;
public MyClass()
{
}
public string Property2 { get; set; }
protected int Property1 { get; set; }
public static void Static1()
{
}
private static void Static2()
{
}
public void Method1()
{
}
protected void Method2()
{
}
private void Method3()
{
}
}
```
## Enum
* Усі члени enum мають бути пронумеровані
* Кожен член повинен бути на своєму рядку
* Кожен член називається з великої літери
### Приклади
:broken_heart:
```csharp=
public enum UserStatus { active, inactive }
```
:green_heart:
```csharp=
public enum UserStatus
{
Active = 0,
Inactive = 1
}
```
## Formatting
* Табуляція - *4 пробіли*. Використовувати символ пробілу, а не таб;
* Конструкції **if-else**, **switch**, **for**, **foreach**, **do**, **do-while**, **using** повинні бути обрамлені в дужки ```{ } ``` навіть якщо там один рядок;
* Скобочки повинні бути розташовані одна під одною;
* Після перерахованих вище конструкцій повинен бути порожній рядок;
* Між членами класу має бути порожній рядок;
* З боків бінарного оператора (+, -, *, \ и т.д.) має бути пробіл;
### Приклади
:broken_heart:
```csharp=
public UserModel GetUserById(long id)
{
var user = this.repository.GetById<User>(id);
if (user == null)
{
return UserModel.NullObject;
}
foreach (UserSkills skill in user.Skills)
{
// logic
}
return user.ToUserModel();
}
```
:green_heart:
```csharp=
public UserModel GetUserById(long id)
{
var user = this.repository.GetById<User>(id);
if (user == null)
{
return UserModel.NullObject;
}
foreach (UserSkills skill in user.Skills)
{
// logic
}
return user.ToUserModel();
}
```
:broken_heart:
```csharp=
public class User
{
public User() : this(-1, "No Name", -1)
{
}
public User(long id, string name, int age)
{
this.Id = id;
this.Name = name;
this.Age = age;
}
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
```
:green_heart:
```csharp=
public class User
{
public User() : this(-1, "No Name", -1)
{
}
public User(long id, string name, int age)
{
Id = id;
Name = name;
Age = age;
}
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
```
:broken_heart:
```csharp=
int devision=5/3;
string result = "sdf"+"sdf";
for (int i=0;i<itemCount;i++)
{
}
```
:green_heart:
```csharp=
int devision = 5 / 3;
string result = "sdf" + "sdf";
for (int i = 0; i < itemCount; i++)
{
}
```
:broken_heart:
```csharp=
public void Method() {
if (condition) {
}
}
```
:green_heart:
```csharp=
public void Method()
{
if (condition)
{
}
}
```
:broken_heart:
```csharp=
public void Method()
{
if (condition)
// one line of logic
foreach (var item in collection)
// one line of logic
}
```
:green_heart:
```csharp=
public void Method()
{
if (condition)
{
// one line of logic
}
foreach (var item in collection)
{
// one line of logic
}
}
```
## Clean code
* Кожна програмна сутність (клас, інтерфейс, енам, делегат) має бути у своєму файлі;
* Максимальна кількість параметрів методу - 5;
* Максимальна довжина рядка – 200 символів;
* Максимальна довжина методу – 50 рядків;
* Максимальний рівень вкладеності для конструкцій ```if```, ```foreach``` і т.д. - 2.
## Other suggestions
* Уникайте мертвого умовного коду (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1508).
* Валідуйте аргументи публічних методів (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/CA1062).
* Використовуйте зарезервовані назви типів (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0049).
* Порядок модифікаторів доступу: public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async.
* Для простих присвоювань значень або їх повернення використовуйте умовні вирази з тернарним оператором (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0046).
* Якщо можливо – використовуйте автовластивості (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0032).
* За потреби використовуйте ініціалізатори колекцій (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0028).
* За потреби використовуйте ініціалізатори об'єктів (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0017).
* Використовуйте **Coalesce** вирази для однорядкової перевірки на ```null``` і заміни на підходяще стандартне значення (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0029-ide0030).
* Використовуйте **null-conditional** оператор для однорядкової перевірки на ```null```, якщо необхідно використовувати члени об'єкта (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0031).
* Використовуйте **pattern matching** для перетворення типів (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0020-ide0038 , https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0019).
* Використовуйте **index-from-end** оператор замість ```.Length - 1``` (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0056).
* Використовуйте **range operator** (https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0057).
* Сортуйте блок usings за абеткою (стандартне сортування в VS 2019).