ШПАРГАЛКА

C#

Шпаргалка по C#: структура программы, типы, строки, коллекции List и Dictionary, ООП, исключения, LINQ, async/await и обобщения с примерами.

C# (произносится «си-шарп») — строго типизированный объектно-ориентированный язык от Microsoft, работающий на платформе .NET. Эта шпаргалка собирает базовый синтаксис, типы, коллекции, ООП, обработку исключений, LINQ, async/await и обобщения с короткими рабочими примерами.

Структура программы

Классическая программа состоит из подключения пространств имён (using), объявления собственного пространства имён и точки входа — метода Main.

using System;                 // подключаем пространство имён

namespace MyApp               // своё пространство имён
{
    class Program
    {
        static void Main(string[] args)   // точка входа
        {
            Console.WriteLine("Привет, мир!");  // вывод: Привет, мир!
        }
    }
}

Начиная с C# 9 доступны top-level statements — можно писать код без явного класса и Main:

using System;

Console.WriteLine("Привет!");   // вывод: Привет!

Переменные и типы

В C# есть значимые типы (value types: int, double, bool, struct) и ссылочные типы (reference types: class, string, массивы). Значимые копируются по значению, ссылочные — по ссылке.

int age = 25;             // целое число
double price = 19.99;     // число с плавающей точкой
bool isReady = true;      // логический тип
char grade = 'A';         // символ
string name = "Аня";      // строка (ссылочный тип)

var count = 10;           // var — тип выводится автоматически (int)
var text = "hello";       // string

Nullable-типы позволяют значимому типу принимать значение null. Полезны операторы ?? и ?.:

int? maybe = null;        // nullable int
int value = maybe ?? 0;   // если null, берём 0 -> value = 0

string? s = null;
int len = s?.Length ?? -1;  // безопасный доступ -> len = -1

Разница value и reference

ПризнакValue typeReference type
Примерыint, double, bool, struct, enumclass, string, array, object
Где хранитсяобычно в стекев куче, переменная хранит ссылку
Присваиваниекопируется значениекопируется ссылка
Значение по умолчанию0 / falsenull

Строки

Строки в C# неизменяемы. Удобно использовать интерполяцию через $"..." и дословные строки @"...".

string name = "Аня";
int age = 25;

string msg = $"Меня зовут {name}, мне {age}";  // интерполяция
// msg = "Меня зовут Аня, мне 25"

string path = @"C:\temp\file.txt";  // без экранирования слешей

Полезные методы строк:

string s = "  Hello World  ";
s.Trim();                  // "Hello World"
s.ToUpper();               // "  HELLO WORLD  "
s.Replace("World", "C#");  // "  Hello C#  "
s.Contains("Hello");       // true
"a,b,c".Split(',');        // ["a", "b", "c"]
string.Join("-", "x", "y");// "x-y"
"abc".Substring(1, 2);     // "bc"
$"{3.14159:F2}";           // "3.14" (форматирование)

Массивы и коллекции

Массив имеет фиксированный размер. Для динамических списков используют List<T>, для пар ключ-значение — Dictionary<TKey, TValue>.

int[] nums = { 1, 2, 3 };       // массив
nums[0] = 10;                   // nums = [10, 2, 3]
Console.WriteLine(nums.Length); // 3

List<T> — динамический список:

using System.Collections.Generic;

var list = new List<string>();
list.Add("кот");
list.Add("пёс");
list.Remove("кот");
Console.WriteLine(list.Count);  // 1
Console.WriteLine(list[0]);     // "пёс"

Dictionary<TKey, TValue> — словарь:

var ages = new Dictionary<string, int>();
ages["Аня"] = 25;
ages["Боб"] = 30;

if (ages.ContainsKey("Аня"))
    Console.WriteLine(ages["Аня"]);  // 25

foreach (var pair in ages)
    Console.WriteLine($"{pair.Key}: {pair.Value}");
// Аня: 25
// Боб: 30

Операторы

Арифметические, сравнения и логические операторы. Помните про целочисленное деление и приоритеты.

int a = 7, b = 2;
a + b;   // 9
a - b;   // 5
a * b;   // 14
a / b;   // 3  (целочисленное деление!)
a % b;   // 1  (остаток)
7.0 / 2; // 3.5 (хотя бы один double)
bool x = true, y = false;
x && y;   // false (логическое И)
x || y;   // true  (логическое ИЛИ)
!x;       // false (отрицание)

5 > 3;    // true
5 <= 5;   // true
5 == 5;   // true
5 != 4;   // true

Условия

Конструкция if / else if / else и тернарный оператор.

int score = 75;

if (score >= 90)
    Console.WriteLine("Отлично");
else if (score >= 60)
    Console.WriteLine("Хорошо");   // выведется это
else
    Console.WriteLine("Плохо");

string result = score >= 60 ? "сдал" : "не сдал";  // "сдал"

Классический switch:

int day = 3;
switch (day)
{
    case 1:
        Console.WriteLine("Понедельник");
        break;
    case 3:
        Console.WriteLine("Среда");   // сюда
        break;
    default:
        Console.WriteLine("Другой день");
        break;
}

switch expression (C# 8+) — компактная форма, возвращающая значение:

string name = day switch
{
    1 => "Понедельник",
    3 => "Среда",
    _ => "Другой день"   // _ — все остальные случаи
};
// name = "Среда"

Циклы

Цикл for со счётчиком:

for (int i = 0; i < 3; i++)
    Console.WriteLine(i);
// 0
// 1
// 2

Цикл foreach для перебора коллекции:

var fruits = new[] { "яблоко", "груша" };
foreach (var f in fruits)
    Console.WriteLine(f);
// яблоко
// груша

Циклы while и do/while:

int n = 0;
while (n < 3)
{
    Console.Write(n);  // 012
    n++;
}

int m = 0;
do
{
    Console.Write(m);  // 0 (тело выполнится хотя бы раз)
    m++;
} while (m < 1);

Управление: break прерывает цикл, continue переходит к следующей итерации.

Методы

Метод объявляется с типом возврата, именем и параметрами. void означает «ничего не возвращает».

int Sum(int a, int b)
{
    return a + b;
}

Console.WriteLine(Sum(2, 3));  // 5

// выражение-тело (expression body)
int Square(int x) => x * x;
Console.WriteLine(Square(4));   // 16

Параметры по умолчанию и именованные аргументы:

void Greet(string name, string greeting = "Привет")
{
    Console.WriteLine($"{greeting}, {name}!");
}

Greet("Аня");                    // Привет, Аня!
Greet("Боб", greeting: "Хай");   // Хай, Боб!

ref передаёт переменную по ссылке, out — для возврата нескольких значений:

void Increment(ref int x) => x++;
int a = 5;
Increment(ref a);   // a = 6

bool TryParse(string s, out int result)
{
    return int.TryParse(s, out result);
}
if (TryParse("42", out int num))
    Console.WriteLine(num);  // 42

Перегрузка — несколько методов с одним именем, но разными параметрами:

int Add(int a, int b) => a + b;
double Add(double a, double b) => a + b;

Add(1, 2);       // 3   (int-версия)
Add(1.5, 2.5);   // 4.0 (double-версия)

Лямбды — анонимные функции:

Func<int, int> doubler = x => x * 2;
Console.WriteLine(doubler(5));  // 10

Action<string> print = msg => Console.WriteLine(msg);
print("Лог");  // Лог

ООП: классы и структуры

Класс инкапсулирует данные (поля), свойства и поведение (методы). struct — значимый тип, удобен для маленьких неизменяемых данных.

class Person
{
    // свойство (property) с автоматическим backing field
    public string Name { get; set; }
    public int Age { get; private set; }  // сеттер только внутри класса

    // конструктор
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public void Hello() => Console.WriteLine($"Я {Name}");
}

var p = new Person("Аня", 25);
p.Hello();                  // Я Аня
Console.WriteLine(p.Name);  // Аня
struct Point
{
    public int X;
    public int Y;
    public Point(int x, int y) { X = x; Y = y; }
}

var pt = new Point(1, 2);
Console.WriteLine($"{pt.X}, {pt.Y}");  // 1, 2

Наследование

Класс-потомок наследует поведение базового класса. virtual разрешает переопределение, override переопределяет.

class Animal
{
    public virtual void Voice() => Console.WriteLine("...");
}

class Dog : Animal
{
    public override void Voice() => Console.WriteLine("Гав");
}

Animal a = new Dog();
a.Voice();   // Гав (полиморфизм)

Интерфейсы

Интерфейс описывает контракт — набор членов без реализации.

interface IShape
{
    double Area();
}

class Circle : IShape
{
    private double r;
    public Circle(double radius) => r = radius;
    public double Area() => Math.PI * r * r;
}

IShape shape = new Circle(2);
Console.WriteLine(shape.Area());  // 12.566...

Record

record (C# 9+) — ссылочный тип для неизменяемых данных со сравнением по значению и удобным конструктором.

record User(string Name, int Age);

var u1 = new User("Аня", 25);
var u2 = new User("Аня", 25);
Console.WriteLine(u1 == u2);  // True (сравнение по значению)

var u3 = u1 with { Age = 26 }; // копия с изменением
Console.WriteLine(u3.Age);     // 26

Обработка исключений

Блок try / catch / finally перехватывает ошибки. finally выполняется всегда.

try
{
    int x = int.Parse("не число");  // бросит FormatException
}
catch (FormatException ex)
{
    Console.WriteLine($"Ошибка формата: {ex.Message}");
}
catch (Exception ex)   // более общий обработчик
{
    Console.WriteLine($"Другая ошибка: {ex.Message}");
}
finally
{
    Console.WriteLine("Завершение");  // выполнится в любом случае
}

Своё исключение бросается через throw:

void CheckAge(int age)
{
    if (age < 0)
        throw new ArgumentException("Возраст не может быть отрицательным");
}

LINQ кратко

LINQ позволяет запрашивать коллекции. Чаще всего используют Where (фильтр) и Select (преобразование).

using System.Linq;

var nums = new[] { 1, 2, 3, 4, 5, 6 };

var evens = nums.Where(n => n % 2 == 0);   // 2, 4, 6
var squares = nums.Select(n => n * n);     // 1, 4, 9, 16, 25, 36

var result = nums
    .Where(n => n > 2)
    .Select(n => n * 10)
    .ToList();
// result = [30, 40, 50, 60]

int sum = nums.Sum();        // 21
int max = nums.Max();        // 6
bool any = nums.Any(n => n > 5);  // true

async / await кратко

Асинхронные методы помечаются async и возвращают Task или Task<T>. Оператор await ждёт завершения без блокировки потока.

using System.Threading.Tasks;

async Task<int> GetDataAsync()
{
    await Task.Delay(1000);   // имитация задержки (1 сек)
    return 42;
}

// вызов
int data = await GetDataAsync();
Console.WriteLine(data);  // 42 (через ~1 сек)

Важно: async void используют только для обработчиков событий; в остальных случаях возвращайте Task.

Обобщения (generics) кратко

Обобщения позволяют писать код, работающий с любым типом T, сохраняя типобезопасность.

// обобщённый метод
T First<T>(T[] items) => items[0];

int n = First(new[] { 10, 20 });        // 10
string s = First(new[] { "a", "b" });   // "a"
// обобщённый класс
class Box<T>
{
    public T Value { get; set; }
    public Box(T value) => Value = value;
}

var intBox = new Box<int>(123);
var strBox = new Box<string>("привет");
Console.WriteLine(intBox.Value);  // 123
Console.WriteLine(strBox.Value);  // привет

Ограничения через where сужают допустимые типы:

T Max<T>(T a, T b) where T : IComparable<T>
    => a.CompareTo(b) > 0 ? a : b;

Console.WriteLine(Max(3, 7));  // 7
Поддержать проект