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 type | Reference type |
|---|---|---|
| Примеры | int, double, bool, struct, enum | class, string, array, object |
| Где хранится | обычно в стеке | в куче, переменная хранит ссылку |
| Присваивание | копируется значение | копируется ссылка |
| Значение по умолчанию | 0 / false | null |
Строки
Строки в 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