🔷 C#

Ciclo for em C# (.NET 6): guia detalhado

Условия и циклы в C#: if, switch, foreach и LINQ

Представь, что ты пишешь инструкцию для робота-помощника. «Если на улице дождь — возьми зонт, иначе надень солнечные очки. Повтори каждый шаг 10 раз. Для каждого предмета в списке — проверь его.» Именно это делают условия и циклы в программировании — управляют тем, как и когда выполняется код.

Условный оператор if/else

Оператор if — это «развилка на дороге». Программа проверяет условие и выбирает один из путей.

int age = 16;

// Простой if
if (age >= 18)
{
    Console.WriteLine("Доступ разрешён");
}

// if с else
if (age >= 18)
{
    Console.WriteLine("Взрослый");
}
else
{
    Console.WriteLine("Несовершеннолетний");
}

// Цепочка if-else if-else
int score = 75;

if (score >= 90)
{
    Console.WriteLine("Отлично! (A)");
}
else if (score >= 75)
{
    Console.WriteLine("Хорошо (B)");
}
else if (score >= 60)
{
    Console.WriteLine("Удовлетворительно (C)");
}
else
{
    Console.WriteLine("Нужно подтянуться (F)");
}
// Результат: Хорошо (B)

Операторы сравнения и логические операторы

int a = 10, b = 5;

// Операторы сравнения
Console.WriteLine(a == b);  // false — равно
Console.WriteLine(a != b);  // true  — не равно
Console.WriteLine(a > b);   // true  — больше
Console.WriteLine(a < b);   // false — меньше
Console.WriteLine(a >= b);  // true  — больше или равно
Console.WriteLine(a <= b);  // false — меньше или равно

// Логические операторы
bool x = true, y = false;
Console.WriteLine(x && y);  // false — И (оба должны быть true)
Console.WriteLine(x || y);  // true  — ИЛИ (хотя бы один true)
Console.WriteLine(!x);      // false — НЕ (инверсия)

// Практический пример
int temperature = 25;
bool isSunny = true;

if (temperature > 20 && isSunny)
{
    Console.WriteLine("Отличный день для прогулки!");
}

Тернарный оператор: краткая форма if/else

int age = 20;

// Длинная форма
string status;
if (age >= 18)
{
    status = "взрослый";
}
else
{
    status = "ребёнок";
}

// Краткая форма с тернарным оператором ? :
string status2 = age >= 18 ? "взрослый" : "ребёнок";
Console.WriteLine(status2); // взрослый

// Ещё примеры
int x = 5;
string result = x > 0 ? "положительное" : x < 0 ? "отрицательное" : "ноль";

int max = a > b ? a : b; // Максимум из двух чисел

Оператор switch: много вариантов выбора

Когда вариантов выбора много, цепочка if-else становится громоздкой. Для этого есть оператор switch.

int dayNumber = 3;

// Классический switch
switch (dayNumber)
{
    case 1:
        Console.WriteLine("Понедельник");
        break;
    case 2:
        Console.WriteLine("Вторник");
        break;
    case 3:
        Console.WriteLine("Среда");
        break;
    case 4:
        Console.WriteLine("Четверг");
        break;
    case 5:
        Console.WriteLine("Пятница");
        break;
    case 6:
    case 7:
        Console.WriteLine("Выходной!");
        break;
    default:
        Console.WriteLine("Неверный номер дня");
        break;
}
// Результат: Среда

Switch expression: современный синтаксис (C# 8+)

// Новый элегантный switch expression
int dayNumber = 3;
string dayName = dayNumber switch
{
    1 => "Понедельник",
    2 => "Вторник",
    3 => "Среда",
    4 => "Четверг",
    5 => "Пятница",
    6 or 7 => "Выходной",
    _ => "Неверный день"  // _ это default
};
Console.WriteLine(dayName); // Среда

// Switch с условиями (pattern matching)
int score = 85;
string grade = score switch
{
    >= 90 => "A",
    >= 80 => "B",
    >= 70 => "C",
    >= 60 => "D",
    _     => "F"
};
Console.WriteLine(grade); // B

// Switch по типам
object obj = "Привет";
string description = obj switch
{
    int n    => $"Число: {n}",
    string s => $"Строка длиной {s.Length}",
    bool b   => $"Булево: {b}",
    null     => "null",
    _        => "Неизвестный тип"
};
Console.WriteLine(description); // Строка длиной 6

Цикл for: точное количество повторений

Цикл for используется, когда знаешь точное количество повторений. Представь: «пробеги 10 кругов» — ты знаешь количество.

// Базовый for: от 1 до 10
for (int i = 1; i <= 10; i++)
{
    Console.Write(i + " ");
}
// Результат: 1 2 3 4 5 6 7 8 9 10

Console.WriteLine(); // Перевод строки

// Структура for: (начало; условие продолжения; шаг)
for (int i = 0; i < 5; i++)     // Счёт с нуля: 0,1,2,3,4
for (int i = 10; i >= 1; i--)   // Обратный счёт: 10,9,...,1
for (int i = 0; i < 20; i += 2) // С шагом 2: 0,2,4,...,18
// Таблица умножения на 5
Console.WriteLine("Таблица умножения на 5:");
for (int i = 1; i <= 10; i++)
{
    Console.WriteLine($"5 × {i} = {5 * i}");
}

// Вложенные циклы — таблица умножения 3×3
for (int i = 1; i <= 3; i++)
{
    for (int j = 1; j <= 3; j++)
    {
        Console.Write($"{i * j,3}"); // ,3 — ширина поля 3 символа
    }
    Console.WriteLine();
}
// Результат:
//   1  2  3
//   2  4  6
//   3  6  9

Цикл while: пока условие истинно

// while — как загрузка: крутится пока не закончит
int health = 100;
int damage = 15;

while (health > 0)
{
    Console.WriteLine($"HP: {health}");
    health -= damage;
}
Console.WriteLine("Игрок погиб!");

// Ввод с проверкой
Console.Write("Введите число от 1 до 10: ");
int number;
while (!int.TryParse(Console.ReadLine(), out number) || number < 1 || number > 10)
{
    Console.Write("Неверный ввод! Попробуй снова: ");
}
Console.WriteLine($"Ты ввёл: {number}");

Цикл do-while: минимум одно выполнение

// do-while выполняется хотя бы один раз
int attempts = 0;
string secret = "C#";
string guess;

do
{
    Console.Write("Угадай язык программирования: ");
    guess = Console.ReadLine();
    attempts++;
} while (guess != secret);

Console.WriteLine($"Правильно! Попыток: {attempts}");

Цикл foreach: для каждого элемента

Самый удобный цикл для работы с коллекциями — массивами, списками и другими наборами данных.

// Массив имён
string[] names = { "Алиса", "Борис", "Василий", "Галина" };

foreach (string name in names)
{
    Console.WriteLine($"Привет, {name}!");
}
// Результат:
// Привет, Алиса!
// Привет, Борис!
// Привет, Василий!
// Привет, Галина!

// Список чисел
var numbers = new List { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sum = 0;
foreach (int num in numbers)
{
    sum += num;
}
Console.WriteLine($"Сумма: {sum}"); // 55

// Перебор символов строки
string word = "Привет";
foreach (char c in word)
{
    Console.Write(c + "-"); // П-р-и-в-е-т-
}

break и continue: управление циклом

// break — прерывает цикл полностью
Console.WriteLine("Ищем первое число больше 5:");
int[] numbers = { 1, 3, 7, 2, 9, 4 };
foreach (int n in numbers)
{
    if (n > 5)
    {
        Console.WriteLine($"Нашли: {n}");
        break; // Выходим из цикла
    }
}
// Нашли: 7

// continue — пропускает текущую итерацию
Console.WriteLine("Только чётные числа:");
for (int i = 1; i <= 10; i++)
{
    if (i % 2 != 0) continue; // Пропускаем нечётные
    Console.Write(i + " ");
}
// 2 4 6 8 10

Введение в LINQ: SQL для коллекций

LINQ (Language Integrated Query — встроенный язык запросов) — это мощный инструмент C# для работы с коллекциями. Представь, что у тебя есть база данных в памяти, и ты можешь делать к ней SQL-запросы прямо в коде!

using System.Linq;

var students = new List { "Алиса", "Борис", "Анна", "Виктор", "Антон" };

// WHERE — фильтрация (как SQL WHERE)
var aNames = students.Where(s => s.StartsWith("А")).ToList();
Console.WriteLine(string.Join(", ", aNames)); // Алиса, Анна, Антон

// SELECT — преобразование (как SQL SELECT)
var lengths = students.Select(s => s.Length).ToList();
Console.WriteLine(string.Join(", ", lengths)); // 5, 5, 4, 6, 5

// ORDER BY — сортировка
var sorted = students.OrderBy(s => s).ToList();
Console.WriteLine(string.Join(", ", sorted)); // Алиса, Анна, Антон, Борис, Виктор

// COUNT, SUM, MIN, MAX — агрегация
var scores = new List { 85, 92, 78, 95, 88, 73, 91 };
Console.WriteLine($"Количество: {scores.Count()}");
Console.WriteLine($"Сумма: {scores.Sum()}");
Console.WriteLine($"Среднее: {scores.Average():F1}");
Console.WriteLine($"Максимум: {scores.Max()}");
Console.WriteLine($"Минимум: {scores.Min()}");

// Цепочка операций
var topScores = scores
    .Where(s => s >= 85)      // Только отличники (>=85)
    .OrderByDescending(s => s) // Сортируем по убыванию
    .Take(3)                   // Берём первые 3
    .ToList();
Console.WriteLine(string.Join(", ", topScores)); // 95, 92, 91

Типичные ошибки

Ошибка 1: Бесконечный цикл

// ОПАСНО! Бесконечный цикл — программа зависнет
int i = 0;
while (i < 10)
{
    Console.WriteLine(i);
    // Забыли i++ !!! Цикл никогда не закончится
}

// ПРАВИЛЬНО:
int j = 0;
while (j < 10)
{
    Console.WriteLine(j);
    j++; // Не забываем увеличивать счётчик
}

Ошибка 2: Выход за пределы массива

int[] arr = { 1, 2, 3 }; // Индексы: 0, 1, 2

// ОШИБКА!
// Console.WriteLine(arr[3]); // IndexOutOfRangeException!

// ПРАВИЛЬНО:
for (int i = 0; i < arr.Length; i++) // arr.Length = 3, индексы 0,1,2
{
    Console.WriteLine(arr[i]);
}

Итого

  • ✅ if/else — выбор пути по условию
  • ✅ switch — выбор из многих вариантов; switch expression — современный лаконичный синтаксис
  • ✅ for — цикл с известным числом итераций
  • ✅ while — цикл пока условие истинно
  • ✅ do-while — цикл с гарантированным первым выполнением
  • ✅ foreach — цикл по каждому элементу коллекции
  • ✅ break/continue — прерывание и продолжение цикла
  • ✅ LINQ — мощные запросы к коллекциям (Where, Select, OrderBy, Sum, Max...)

Практический проект: угадай число

// Игра "Угадай число" с подсказками и статистикой
var rng = new Random();
int secret = rng.Next(1, 101); // 1 до 100
int attempts = 0;
int maxAttempts = 7;
bool won = false;

Console.WriteLine("=== Угадай число от 1 до 100 ===");
Console.WriteLine($"У тебя {maxAttempts} попыток. Удачи!");

while (attempts < maxAttempts && !won)
{
    Console.Write($"\nПопытка {attempts + 1}/{maxAttempts}: ");
    
    if (!int.TryParse(Console.ReadLine(), out int guess) || guess < 1 || guess > 100)
    {
        Console.WriteLine("Введи число от 1 до 100!");
        continue;
    }
    
    attempts++;
    int diff = Math.Abs(secret - guess);
    
    if (guess == secret)
    {
        won = true;
    }
    else
    {
        string hint = diff switch
        {
            1 => "🔥 Горячо! Очень близко!",
            <= 5 => "♨️ Тепло, совсем рядом",
            <= 15 => "😊 Тепловато",
            <= 30 => "🌡️ Прохладно",
            _ => "❄️ Холодно!"
        };
        
        string direction = guess < secret ? "Больше ↑" : "Меньше ↓";
        Console.WriteLine($"{hint} ({direction})");
    }
}

if (won)
    Console.WriteLine($"\n🎉 Поздравляю! Ты угадал {secret} за {attempts} попыток!");
else
    Console.WriteLine($"\n😔 Не угадал. Загаданное число: {secret}");

LINQ: query синтаксис vs методный

record Product(string Name, string Category, decimal Price, int Stock);

var products = new List
{
    new("Ноутбук",      "Электроника", 89999m, 5),
    new("Мышь",         "Электроника", 1299m,  50),
    new("Стол",         "Мебель",      15000m, 10),
    new("Кресло",       "Мебель",      25000m, 7),
    new("Наушники",     "Электроника", 8999m,  20),
    new("Лампа",        "Мебель",      3500m,  15),
};

// Методный синтаксис
var electronics = products
    .Where(p => p.Category == "Электроника")
    .OrderBy(p => p.Price)
    .Select(p => $"{p.Name}: {p.Price:C} (осталось: {p.Stock})")
    .ToList();

Console.WriteLine("Электроника по возрастанию цены:");
electronics.ForEach(Console.WriteLine);

// Query синтаксис (более похож на SQL)
var expensive = 
    from p in products
    where p.Price > 10000
    orderby p.Price descending
    select new { p.Name, p.Price, p.Category };

Console.WriteLine("\nДорогие товары (>10000):");
foreach (var p in expensive)
    Console.WriteLine($"  {p.Name} ({p.Category}): {p.Price:C}");

// Агрегация по категориям
var byCategory = products
    .GroupBy(p => p.Category)
    .Select(g => new {
        Category = g.Key,
        Count = g.Count(),
        TotalValue = g.Sum(p => p.Price * p.Stock),
        AvgPrice = g.Average(p => p.Price)
    });

Console.WriteLine("\nСтатистика по категориям:");
foreach (var c in byCategory)
    Console.WriteLine($"  {c.Category}: {c.Count} товаров, общая стоимость: {c.TotalValue:C}");

Итого

  • ✅ if/else — ветвление по условию
  • ✅ switch expression — элегантный выбор из вариантов
  • ✅ for/while/do-while/foreach — все виды циклов
  • ✅ break/continue — управление циклом
  • ✅ LINQ — мощная обработка коллекций за одну строку
  • ✅ Тернарный оператор ? : — краткая форма if/else

Вложенные структуры управления

// Матрица — вложенные циклы
int[,] matrix = {
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 }
};

Console.WriteLine("Матрица 3×3:");
for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 3; j++)
        Console.Write($"{matrix[i, j],4}");
    Console.WriteLine();
}

// Найти максимум в матрице
int max = matrix[0, 0];
(int row, int col) maxPos = (0, 0);
for (int i = 0; i < 3; i++)
    for (int j = 0; j < 3; j++)
        if (matrix[i, j] > max)
        {
            max = matrix[i, j];
            maxPos = (i, j);
        }
Console.WriteLine($"Максимум: {max} на позиции ({maxPos.row}, {maxPos.col})");

Работа с массивами и LINQ

// Полезные LINQ-запросы для реальных задач
var grades = new[] { 85, 92, 78, 95, 88, 73, 91, 67, 84, 96 };

// Статистика
Console.WriteLine($"Оценки: {string.Join(", ", grades)}");
Console.WriteLine($"Средняя: {grades.Average():F1}");
Console.WriteLine($"Выше среднего: {grades.Count(g => g > grades.Average())}");
Console.WriteLine($"Топ-3: {string.Join(", ", grades.OrderByDescending(g => g).Take(3))}");

// Гистограмма
var histogram = grades
    .GroupBy(g => g / 10 * 10)  // Группируем по десяткам
    .OrderBy(g => g.Key)
    .Select(g => $"{g.Key}-{g.Key+9}: {'*' + new string('*', g.Count() - 1),-15} ({g.Count()})");
Console.WriteLine("\nГистограмма:");
foreach (var bar in histogram)
    Console.WriteLine($"  {bar}");