Загрузка данных


using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        // List<T> — динамический массив, ТИПИЗИРОВАННЫЙ.
        // Компилятор не даст положить сюда строку, если T = int.
        List<int> numbers = new List<int> { 5, 3, 8, 1, 9, 3 };

        numbers.Add(7);           // добавить в конец
        numbers.Insert(0, 100);   // вставить по индексу
        numbers.Remove(3);        // удалить первое вхождение
        numbers.RemoveAt(0);      // удалить по индексу

        Console.WriteLine("Числа: " + string.Join(", ", numbers));
        Console.WriteLine($"Count = {numbers.Count}");

        numbers.Sort();           // сортировка по возрастанию
        Console.WriteLine("Отсортировано: " + string.Join(", ", numbers));

        // LINQ поверх List<T>
        Console.WriteLine($"Сумма: {numbers.Sum()}");
        Console.WriteLine($"Среднее: {numbers.Average():F2}");
        Console.WriteLine($"Максимум: {numbers.Max()}");


        // Dictionary<TKey, TValue> — хеш-таблица «ключ → значение».
        // Ключи ДОЛЖНЫ быть уникальны, иначе будет исключение.
        var phoneBook = new Dictionary<string, string>
        {
            ["Иван"] = "+7-900-111-11-11",
            ["Мария"] = "+7-900-222-22-22",
            ["Пётр"] = "+7-900-333-33-33"
        };

        // Безопасное добавление через TryAdd — не бросает исключение.
        phoneBook.TryAdd("Иван", "+7-000-000-00-00"); // проигнорируется

        // Перебор словаря: KeyValuePair<K,V>.
        foreach (var pair in phoneBook)
        {
            Console.WriteLine($"{pair.Key}: {pair.Value}");
        }

        // Безопасное извлечение через TryGetValue.
        if (phoneBook.TryGetValue("Мария", out string phone))
            Console.WriteLine($"Телефон Марии: {phone}");

        Console.WriteLine($"Есть ли Пётр? {phoneBook.ContainsKey("Пётр")}");


        // Queue<T> — очередь, работает по принципу FIFO (первым пришёл — первым вышел).
        var queue = new Queue<string>();
        queue.Enqueue("Задача 1");
        queue.Enqueue("Задача 2");
        queue.Enqueue("Задача 3");

        Console.WriteLine($"В очереди: {queue.Count}");
        while (queue.Count > 0)
        {
            // Dequeue достаёт и удаляет элемент из начала очереди.
            Console.WriteLine("Обрабатываю: " + queue.Dequeue());
        }

        // Stack<T> — стек, работает по принципу LIFO (последним пришёл — первым вышел).
        var stack = new Stack<int>();
        stack.Push(1);
        stack.Push(2);
        stack.Push(3);

        while (stack.Count > 0)
        {
            // Pop достаёт элемент с вершины стека.
            Console.WriteLine("Со стека: " + stack.Pop());
        }


        // HashSet<T> хранит ТОЛЬКО уникальные значения.
        // Внутри — хеш-таблица, поэтому Contains работает за O(1).
        var setA = new HashSet<int> { 1, 2, 3, 4, 5 };
        var setB = new HashSet<int> { 4, 5, 6, 7 };

        setA.Add(3);  // проигнорируется, 3 уже есть

        Console.WriteLine("Объединение: " + string.Join(", ", setA.Union(setB)));
        Console.WriteLine("Пересечение: " + string.Join(", ", setA.Intersect(setB)));
        Console.WriteLine("Разность A\\B: " + string.Join(", ", setA.Except(setB)));


        // Box<T>
        var intBox = new Box<int>(42);
        var strBox = new Box<string>("Привет");

        Console.WriteLine(intBox);          // Box<Int32>(42)
        Console.WriteLine(strBox);          // Box<String>(Привет)

        intBox.Set(100);
        Console.WriteLine(intBox.Get());    // 100

        // strBox.Set(5); // × Ошибка компиляции: ожидается string, получено int


        // Pair<TKey, TValue>
        var pair1 = new Pair<string, int>("Возраст", 25);
        var pair2 = new Pair<int, string>(1, "Один");

        Console.WriteLine(pair1); // [Возраст => 25]
        Console.WriteLine(pair2); // [1 => Один]


        // Обобщённый метод
        Console.WriteLine(Max(3, 7));           // 7
        Console.WriteLine(Max("abc", "xyz"));   // xyz
        Console.WriteLine(Max(3.14, 2.71));     // 3.14


        // MyList<T>
        var myList = new MyList<string>();
        myList.Add("раз");
        myList.Add("два");
        myList.Add("три");

        for (int i = 0; i < myList.Count; i++)
            Console.WriteLine(myList[i]);


        // Старый необобщённый ArrayList хранит object — это плохо:
        var badList = new System.Collections.ArrayList();
        badList.Add(1);
        badList.Add("строка");  // компилятор не против!
        badList.Add(3.14);
        // int x = (int)badList[1]; // × InvalidCastException в рантайме!
        // List<T> такую ошибку поймает ещё при компиляции.
    }

    // Обобщённые методы — как обобщённые классы, но для одного метода.
    // where T : IComparable<T> — ограничение: T должен уметь сравниваться.
    static T Max<T>(T a, T b) where T : IComparable<T>
    {
        return a.CompareTo(b) > 0 ? a : b;
    }
}

// Параметр T — это "заглушка" типа, которая подставится
// при создании объекта: new Box<int>(...), new Box<string>(...) и т.д.
class Box<T>
{
    private T _value;  // тип поля определяется при создании

    public Box(T value)
    {
        _value = value;
    }

    public T Get()
    {
        return _value;
    }

    public void Set(T value)
    {
        _value = value;
    }

    // Переопределение ToString использует значение.
    public override string ToString() => $"Box<{typeof(T).Name}>({_value})";
}

// Параметров типа может быть несколько: <TKey, TValue>.
class Pair<TKey, TValue>
{
    public TKey Key { get; }
    public TValue Value { get; }

    public Pair(TKey key, TValue value)
    {
        Key = key;
        Value = value;
    }

    public override string ToString() => $"[{Key} => {Value}]";
}

// Простая реализация динамического массива — для понимания, как устроен List<T>.
class MyList<T>
{
    private T[] _items = new T[4];  // стартовая ёмкость
    public int Count { get; private set; }

    public void Add(T item)
    {
        if (Count == _items.Length)
            Array.Resize(ref _items, _items.Length * 2);  // расширяем вдвое
        _items[Count++] = item;
    }

    // Индексатор — позволяет писать list[0], list[1] и т.д.
    public T this[int index]
    {
        get
        {
            if (index < 0 || index >= Count)
                throw new IndexOutOfRangeException();
            return _items[index];
        }
    }
}