--- tags: guides --- # C# Coding guidelines :warning: OBSOLETE New page - https://hackmd.io/@w9ExEETAR0Ko_y7OGGa1IQ/r1eYwav1t ## Naming * Общее правило для именования сущностей - **UpperCamelCase**. * С маленькой буквы начинаются: 1. Поля; 2. Локальные переменные; 3. Формальные параметры метода. * Имена солюшенов, проджей, папок - **UpperCamelCase**. * * Не использовать символ нижнего подчеркивания (```_```) в именах. * Ко всем none-static членам внутри класса обращаться через ключевое слово ```this```. * Имена интерфейсов начинаются с префикса ```I```. * Имена generic-параметров начинаются с префикса ```T```. ### Примеры :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() { } public void Method2() { } private void Method3() { } } ``` ## 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) { this.Id = id; this.Name = name; this.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.