---
title: Типы данных
seo:
  title: "Типы данных — С# Developer"
  description: "Тема «Типы данных» для собеседования С# Developer. Какие типы данных вы знаете? Какие примитивные типы знаете?"
---

[Все темы С# Developer](/s-developer)

## <strong>Какие типы данных вы знаете?</strong> [#q-14bee738d69b819885cffff88767e5be]

Типы данных в <code>C&#35;</code>&#58;

{/* prettier-ignore */}
1. <strong>Простые типы (</strong><code>Value Types</code><strong>)</strong>&#58;

    - <strong>Целые числа</strong>&#58;

        - <code>byte</code>, <code>sbyte</code>

        - <code>short</code>, <code>ushort</code>

        - <code>int</code>, <code>uint</code>

        - <code>long</code>, <code>ulong</code>

    - <strong>Числа с плавающей точкой</strong>&#58;

        - <code>float</code>

        - <code>double</code>

        - <code>decimal</code>

    - <strong>Символы и логические</strong>&#58;

        - <code>char</code>

        - <code>bool</code>

1. <strong>Структуры</strong>&#58;

    - Пользовательские типы, определенные с помощью <code>struct</code>.

1. <strong>Перечисления (</strong><code>Enums</code><strong>)</strong>&#58;

    - Определяются с помощью <code>enum</code>.

1. <strong>Ссылочные типы (</strong><code>Reference Types</code><strong>)</strong>&#58;

    - <strong>Объекты</strong>&#58;

        - <code>object</code> (базовый тип для всех типов)

    - <strong>Строки</strong>&#58;

        - <code>string</code>

    - <strong>Интерфейсы</strong>&#58;

        - Определяются с помощью <code>interface</code>.

    - <strong>Массивы</strong>&#58;

        - Одномерные и многомерные массивы.

1. <code>Nullable</code> <strong>типы</strong>&#58;

    - Для работы с типами, которые могут содержать null (<code>int&#63;</code>, <code>double&#63;</code>).

1. <strong>Динамические типы (Dynamic Types)</strong>&#58;

    - dynamic переносит проверку доступности операций и выбор перегрузок на время выполнения. Он не меняет тип самого объекта; переменной можно присваивать значения разных типов.

:::note[Ссылки для изучения]

1. [Типы данных в C#](https://metanit.com/sharp/tutorial/2.1.php)
   :::

---

## <strong>Какие примитивные типы знаете?</strong> [#q-14bee738d69b81588894d0ad2050fed9]

Примитивные типы данных в <code>C&#35;</code>&#58;

{/* prettier-ignore */}
1. <strong>Целые числа</strong>&#58;

    - <code>byte</code>&#58; 8-битное целое число без знака (0 до 255)

    - <code>sbyte</code>&#58; 8-битное целое число со знаком (-128 до 127)

    - <code>short</code>&#58; 16-битное целое число со знаком (-32,768 до 32,767)

    - <code>ushort</code>&#58; 16-битное целое число без знака (0 до 65,535)

    - <code>int</code>&#58; 32-битное целое число со знаком (-2,147,483,648 до 2,147,483,647)

    - <code>uint</code>&#58; 32-битное целое число без знака (0 до 4,294,967,295)

    - <code>long</code>&#58; 64-битное целое число со знаком (-9,223,372,036,854,775,808 до 9,223,372,036,854,775,807)

    - <code>ulong</code>&#58; 64-битное целое число без знака (0 до 18,446,744,073,709,551,615)

1. <strong>Числа с плавающей точкой</strong>&#58;

    - <code>float</code>&#58; 32-битное число с плавающей точкой одинарной точности (~ ±1.5e−45 до ±3.4e38, точность ~7 цифр)

    - <code>double</code>&#58; 64-битное число с плавающей точкой двойной точности (~ ±5.0e−324 до ±1.7e308, точность ~15-16 цифр)

    - <code>decimal</code>&#58; 128-битное десятичное число с плавающей точкой высокой точности (точность ~28-29 цифр), часто используется для финансовых расчетов.

1. <strong>Символы и логические значения</strong>&#58;

    - char&#58; 16-битная кодовая единица UTF-16. Одна кодовая точка за пределами BMP представляется парой char, а видимый символ может включать несколько кодовых точек.

    - <code>bool</code>&#58; Логическое значение (<code>true</code> или <code>false</code>)

:::note[Ссылки для изучения]

1. [Примитивные типы данных](https://learn.microsoft.com/ru-ru/dotnet/framework/data/adonet/entity-data-model-primitive-data-types)
   :::

---

## <strong>Что такое</strong> <code>Nullable</code><strong>-тип?</strong> [#q-14bee738d69b8124867bec46e8268e01]

<code>Nullable</code>
<strong>-тип</strong> — это тип данных в C#, который может содержать обычное
значение своего типа или значение <code>null</code>. Он позволяет работать с
типами значений (value types), такими как <code>int</code>, <code>double</code>,
и т. д., которые по умолчанию не могут быть <code>null</code>.

#### Основные особенности&#58;

{/* prettier-ignore */}
1. <strong>Объявление</strong>&#58;

    - Nullable-тип объявляется с помощью знака <code>&#63;</code> после типа или с использованием <code>Nullable&#60;T&#62;</code>.

    - Пример&#58; <code>int&#63;</code>, <code>Nullable&#60;int&#62;</code>

1. <strong>Использование</strong>&#58;

    - Nullable-типы могут принимать значение <code>null</code>, что полезно для представления отсутствующих или неопределенных данных.

    - Пример&#58;

        ```csharp
        int? nullableInt = null;
        if (nullableInt.HasValue)
        {
            Console.WriteLine(nullableInt.Value);
        }
        else
        {
            Console.WriteLine("Value is null");
        }
        ```

1. <strong>Свойства и методы</strong>&#58;

    - <code>HasValue</code>&#58; Возвращает <code>true</code>, если переменная имеет значение, и <code>false</code>, если она равна <code>null</code>.

    - <code>Value</code>&#58; Возвращает значение переменной, если оно существует; в противном случае выбрасывает исключение.

#### Пример&#58;

```csharp
int? number = null;

if (number.HasValue)
{
    Console.WriteLine($"Number: {number.Value}");
}
else
{
    Console.WriteLine("Number is null");
}
```

:::note[Ссылки для изучения]

1. [Тип данных Nullable](https://devpractice.ru/c-sharp-lesson-2-data-types/)
   :::

---

## <strong>Что такое тип значения, а что такое тип ссылки? Что из этого</strong> <code>class</code><strong>, а что</strong> <code>struct</code><strong>? В каком участке памяти они хранятся?</strong> [#q-14bee738d69b81c8a8c6d2ebed510df0]

Типы значения и типы ссылки&#58;

<strong>Тип значения (Value Type)</strong>&#58;

- <strong>Описание</strong>&#58; Хранит данные непосредственно в своей памяти.

- <strong>Примеры</strong>&#58; <code>struct</code>, <code>int</code>,
  <code>double</code>, <code>bool</code>

- Значение копируется при присваивании; размещение зависит от контекста. Оно может быть локальной переменной, полем объекта в куче, элементом массива или упакованным объектом.

- <strong>Пример</strong>&#58;

  ```csharp
  struct Point
  {
      public int X;
      public int Y;
  }
  ```

<strong>Тип ссылки (Reference Type)</strong>&#58;

- <strong>Описание</strong>&#58; Хранит ссылку на данные, которые находятся в
  другом месте памяти.

- <strong>Примеры</strong>&#58; <code>class</code>, <code>string</code>,
  <code>array</code>, <code>object</code>

- <strong>Хранение</strong>&#58; В управляемой куче (Heap)

- <strong>Пример</strong>&#58;

  ```csharp
  class Person
  {
      public string Name;
      public int Age;
  }
  ```

#### Сравнение

{/* prettier-ignore */}
- <strong>Тип значения</strong>&#58;

    - Значение копируется при присваивании; размещение зависит от контекста. Оно может быть локальной переменной, полем объекта в куче, элементом массива или упакованным объектом.

    - Примеры&#58; <code>struct</code>, <code>int</code>, <code>bool</code>

    - Копируются при присваивании другой переменной.

- <strong>Тип ссылки</strong>&#58;

    - Объект обычно находится в управляемой куче. Сама ссылка может храниться в локальной переменной, регистре, поле другого объекта или элементе массива.

    - Примеры&#58; <code>class</code>, <code>string</code>, <code>array</code>

    - При присваивании другой переменной копируется только ссылка, а не сами данные.

:::note[Ссылки для изучения]

1. [Типы значений и ссылочные типы](https://metanit.com/sharp/tutorial/2.16.php)
   :::

---

## <strong>Чем отличаются value от reference</strong> <code>type</code><strong>?</strong> <code>String</code> <strong>- это</strong> <code>reference</code> <strong>или</strong> <code>value</code><strong>?</strong> [#q-14bee738d69b818faeb0cc153fb470cb]

Отличия Value Type и Reference Type&#58;

<strong>Value Type (Тип значения)</strong>&#58;

- Значение копируется при присваивании; размещение зависит от контекста. Оно может быть локальной переменной, полем объекта в куче, элементом массива или упакованным объектом.

- <strong>Копирование</strong>&#58; Копируется само значение при присваивании
  другой переменной.

- <strong>Примеры</strong>&#58; <code>int</code>, <code>double</code>,
  <code>bool</code>, <code>struct</code>.

- <strong>Семантика</strong>&#58; Каждый экземпляр содержит собственные данные.

<strong>Reference Type (Тип ссылки)</strong>&#58;

- Объект обычно находится в управляемой куче. Сама ссылка может храниться в локальной переменной, регистре, поле другого объекта или элементе массива.

- <strong>Копирование</strong>&#58; Копируется ссылка на данные при присваивании
  другой переменной.

- <strong>Примеры</strong>&#58; <code>class</code>, <code>string</code>,
  <code>array</code>, <code>object</code>.

- <strong>Семантика</strong>&#58; Несколько переменных могут ссылаться на один и
  тот же объект.

#### String

<strong>String</strong> — это <strong>reference type</strong> (тип ссылки).

- <strong>Поведение</strong>&#58; Хотя <code>string</code> является reference
  type, он ведет себя как immutable (неизменяемый) объект, то есть любые
  изменения строки создают новый объект в памяти.

#### Пример&#58;

```csharp
// Value Type
int a = 10;
int b = a; // b получает копию значения a
b = 20;
Console.WriteLine(a); // 10
Console.WriteLine(b); // 20

// Reference Type
string s1 = "Hello";
string s2 = s1; // s2 ссылается на тот же объект, что и s1
s2 = "World";
Console.WriteLine(s1); // Hello
Console.WriteLine(s2); // World
```

#### Итог

- Значение копируется при присваивании; размещение зависит от контекста. Оно может быть локальной переменной, полем объекта в куче, элементом массива или упакованным объектом.

- <strong>Reference Type</strong>&#58; Хранится в куче, копируется по ссылке.

- <strong>String</strong>&#58; Reference type, ведет себя как immutable объект.

:::note[Ссылки для изучения]

1. [Популярные заблуждения о C#](https://habr.com/ru/articles/541786/)
   :::

---

## <strong>В чем отличие между</strong> <code>string builder</code> <strong>и</strong> <code>string</code><strong>?</strong> [#q-14bee738d69b816c8041ed274f106410]

<code>String</code> и <code>StringBuilder</code> — оба класса используются для
работы со строками в C#, но они имеют принципиальные различия в способе
управления строковыми данными.

#### String

{/* prettier-ignore */}
1. <strong>Неизменяемость (Immutable)</strong>&#58;

    - <code>String</code> объекты являются неизменяемыми. Любое изменение строки приводит к созданию нового объекта в памяти.

    - Пример&#58;

        ```csharp
        string str = "Hello";
        str += " World"; // Создается новый объект строки
        ```

1. <strong>Производительность</strong>&#58;

    - Из-за неизменяемости любые частые изменения строк могут привести к значительным накладным расходам по памяти и производительности.

    - Подходит для случаев, когда строки изменяются редко.

1. <strong>Простота использования</strong>&#58;

    - Легко использовать для простых операций со строками.

#### StringBuilder

{/* prettier-ignore */}
1. <strong>Изменяемость (Mutable)</strong>&#58;

    - <code>StringBuilder</code> объекты являются изменяемыми. Они позволяют изменять содержимое строки без создания новых объектов.

    - Пример&#58;

        ```csharp
        StringBuilder sb = new StringBuilder("Hello");
        sb.Append(" World"); // Изменяется существующий объект
        ```

1. <strong>Производительность</strong>&#58;

    - Более эффективен для частых и многочисленных изменений строк, таких как конкатенация в циклах.

    - Подходит для ситуаций, когда строки изменяются часто.

1. <strong>Использование</strong>&#58;

    - Требует немного больше кода для выполнения простых операций, но значительно улучшает производительность при частых изменениях.

:::note[Ссылки для изучения]

1. [Разница между string и string builder](https://tr-page.yandex.ru/translate?lang=en-ru&url=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F3069416%2Fdifference-between-string-and-stringbuilder-in-c-sharp)
   :::

---

## <strong>Что такое дженерики? Какие проблемы они решают?</strong> [#q-14bee738d69b8164a95cd51c2cdf795a]

<strong>Дженерики</strong> — это механизм в C#, который позволяет создавать
классы, методы и структуры с отложенной спецификацией типов, обеспечивая
типобезопасность и повторное использование кода.

#### Проблемы, которые решают дженерики&#58;

{/* prettier-ignore */}
1. <strong>Типобезопасность</strong>&#58;

    - Обеспечивают проверку типов во время компиляции, снижая вероятность ошибок времени выполнения.

1. <strong>Повторное использование кода</strong>&#58;

    - Позволяют создавать универсальные классы и методы, которые могут работать с любыми типами данных, избегая дублирования кода.

1. <strong>Производительность</strong>&#58;

    - Устраняют необходимость в боксе и анбоксе (boxing/unboxing) для типов значений, что улучшает производительность и снижает накладные расходы.

#### Пример использования дженериков&#58;

```csharp
// Определение дженерикового класса
public class GenericList<T>
{
    private T[] items;
    private int count;

    public GenericList(int capacity)
    {
        items = new T[capacity];
    }

    public void Add(T item)
    {
        items[count++] = item;
    }

    public T Get(int index)
    {
        return items[index];
    }
}

// Использование дженерикового класса
GenericList<int> intList = new GenericList<int>(10);
intList.Add(1);
intList.Add(2);
int number = intList.Get(0);

GenericList<string> stringList = new GenericList<string>(10);
stringList.Add("Hello");
stringList.Add("World");
string text = stringList.Get(0);
```

Дженерики в C# обеспечивают типобезопасность, повторное использование кода и улучшенную производительность, решая проблемы, связанные с работой с различными типами данных и избегая дублирования кода.

:::note[Ссылки для изучения]

1. [Дженерики в .NET](https://learn.microsoft.com/en-us/dotnet/standard/generics/)
   :::

---

## <strong>Что такое</strong> <code>boxing</code> <strong>/</strong> <code>unboxing</code><strong>?</strong> [#q-14bee738d69b81efb7d3dfe6a8238b9f]

<code>Boxing</code> и <code>Unboxing</code> — это процессы в C#, связанные с
преобразованием значимых типов (value types) в ссылочные типы (reference types)
и наоборот.

<strong>Boxing</strong> — это процесс упаковки значимого типа (value type) в
объект (object) или любой интерфейсный тип, реализованный этим значимым типом.

- <strong>Цель</strong>&#58; Преобразование value type в reference type.

- <strong>Пример</strong>&#58;

  ```csharp
  int num = 123;
  object boxed = num; // Boxing
  ```

<strong>Unboxing</strong> — это процесс распаковки объекта (object) или
интерфейса обратно в значимый тип (value type).

- <strong>Цель</strong>&#58; Преобразование reference type обратно в value type.

- <strong>Пример</strong>&#58;

  ```csharp
  object boxed = 123;
  int num = (int)boxed; // Unboxing
  ```

#### Пример полного цикла&#58;

```csharp
int num = 123;       // Значимый тип (value type)
object boxed = num;  // Boxing: упаковывание в объект
int unboxed = (int)boxed; // Unboxing: распаковывание обратно в значимый тип
```

#### Итог

- <strong>Boxing</strong>&#58; Преобразование значимого типа в ссылочный тип,
  упаковка значения.

- <strong>Unboxing</strong>&#58; Преобразование ссылочного типа обратно в
  значимый тип, распаковка значения.

:::note[Ссылки для изучения]

1. [Упаковка - преобразование и распаковка в .NET](https://learn.microsoft.com/ru-ru/dotnet/csharp/programming-guide/types/boxing-and-unboxing)
   :::

---

## Чем отличаются Array, List, HashSet и Dictionary по применению и сложности операций? [#q-14bee738d69b81acb0c4d5b047bb0cdf]

<code>Array</code>, <code>List</code>, <code>HashSet</code>,
<code>Dictionary</code> в C#&#58;

<strong>Array</strong>&#58;

{/* prettier-ignore */}
- <strong>Описание</strong>&#58; Фиксированного размера, индексированная коллекция элементов одного типа.

- <strong>Пример</strong>&#58;

    ```csharp
    int[] array = new int[5] {1, 2, 3, 4, 5};
    ```

- <strong>Сложность</strong>&#58;

    - Доступ по индексу&#58; O(1); линейный поиск значения&#58; O(n).

    - Вставка&#58; N/A (фиксированный размер)

    - Удаление&#58; N/A (фиксированный размер)

<strong>List</strong>&#58;

{/* prettier-ignore */}
- <strong>Описание</strong>&#58; Динамически изменяемый массив.

- <strong>Пример</strong>&#58;

    ```csharp
    List<int> list = new List<int> {1, 2, 3, 4, 5};
    list.Add(6);
    ```

- <strong>Сложность</strong>&#58;

    - Поиск&#58; O(1) (по индексу), O(n) (по значению)

    - Добавление в конец&#58; амортизированное O(1), при расширении массива O(n). Вставка в середину&#58; O(n).

    - Удаление&#58; O(n)

<strong>HashSet</strong>&#58;

{/* prettier-ignore */}
- <strong>Описание</strong>&#58; Коллекция уникальных элементов, неупорядоченная.

- <strong>Пример</strong>&#58;

    ```csharp
    HashSet<int> set = new HashSet<int> {1, 2, 3};
    set.Add(4);
    ```

- <strong>Сложность</strong>&#58;

    - Поиск&#58; в среднем O(1), в худшем случае O(n) при большом числе коллизий.

    - Вставка&#58; ожидаемое амортизированное O(1); рост таблицы или множество коллизий могут потребовать O(n).

    - Удаление&#58; в среднем O(1), в худшем случае O(n) из-за поиска среди коллизий.

<strong>Dictionary</strong>&#58;

{/* prettier-ignore */}
- <strong>Описание</strong>&#58; Коллекция пар "ключ-значение", быстрый доступ по ключу.

- <strong>Пример</strong>&#58;

    ```csharp
    Dictionary<int, string> dict = new Dictionary<int, string>();
    dict[1] = "One";
    dict[2] = "Two";
    ```

- <strong>Сложность</strong>&#58;

    - Поиск&#58; в среднем O(1), в худшем случае O(n) при большом числе коллизий.

    - Вставка&#58; ожидаемое амортизированное O(1); рост таблицы или множество коллизий могут потребовать O(n).

    - Удаление&#58; в среднем O(1), в худшем случае O(n) из-за поиска среди коллизий.

:::note[Ссылки для изучения]

1. [Стандартные коллекции в .NET](https://learn.microsoft.com/ru-ru/dotnet/standard/collections/)
   :::

---

## <strong>Какие знаете коллекции?</strong> [#q-14bee738d69b817ab047db4a093ee9f0]

Коллекции в C#&#58;

<strong>1&#46; Списки (Lists)</strong>&#58;

- <strong>List&#60;T&#62;</strong>&#58; Динамически изменяемый массив.

- Пример&#58; <code>List&#60;int&#62; numbers &#61; new List&#60;int&#62;&#40;&#41;&#59;</code>

<strong>2&#46; Множества (Sets)</strong>&#58;

- <strong>HashSet&#60;T&#62;</strong>&#58; Коллекция уникальных элементов,
  неупорядоченная.

- Пример&#58; <code>HashSet&#60;int&#62; uniqueNumbers &#61; new HashSet&#60;int&#62;&#40;&#41;&#59;</code>

<strong>3&#46; Словари (Dictionaries)</strong>&#58;

- <strong>Dictionary&#60;TKey, TValue&#62;</strong>&#58; Коллекция пар
  "ключ-значение".

- Пример&#58; <code>Dictionary&#60;int&#44; string&#62; dict &#61; new Dictionary&#60;int&#44; string&#62;&#40;&#41;&#59;</code>

<strong>4&#46; Очереди (Queues)</strong>&#58;

- <strong>Queue&#60;T&#62;</strong>&#58; Коллекция FIFO (First-In-First-Out).

- Пример&#58; <code>Queue&#60;int&#62; queue &#61; new Queue&#60;int&#62;&#40;&#41;&#59;</code>

<strong>5&#46; Стэки (Stacks)</strong>&#58;

- <strong>Stack&#60;T&#62;</strong>&#58; Коллекция LIFO (Last-In-First-Out).

- Пример&#58; <code>Stack&#60;int&#62; stack &#61; new Stack&#60;int&#62;&#40;&#41;&#59;</code>

<strong>6&#46; Связанные списки (Linked Lists)</strong>&#58;

- <strong>LinkedList&#60;T&#62;</strong>&#58; Двусвязный список.

- Пример&#58; <code>LinkedList&#60;int&#62; linkedList &#61; new LinkedList&#60;int&#62;&#40;&#41;&#59;</code>

<strong>7&#46; Наборы (Sorted Sets)</strong>&#58;

- <strong>SortedSet&#60;T&#62;</strong>&#58; Упорядоченная коллекция уникальных
  элементов.

- Пример&#58; <code>SortedSet&#60;int&#62; sortedSet &#61; new SortedSet&#60;int&#62;&#40;&#41;&#59;</code>

<strong>8&#46; Словари (Sorted Dictionaries)</strong>&#58;

- <strong>SortedDictionary&#60;TKey, TValue&#62;</strong>&#58; Упорядоченная
  коллекция пар "ключ-значение".

- Пример&#58; <code>SortedDictionary&#60;int&#44; string&#62; sortedDict &#61; new SortedDictionary&#60;int&#44; string&#62;&#40;&#41;&#59;</code>

<strong>9&#46; Списки на массиве (Array Lists)</strong>&#58;

- <strong>ArrayList</strong>&#58; Динамический массив объектов (не
  типизированный).

- Пример&#58; <code>ArrayList arrayList &#61; new ArrayList&#40;&#41;&#59;</code>

:::note[Ссылки для изучения]

1. [Коллекции в .NET](https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/collections)
   :::

---

## <strong>Что делает оператор</strong> <code>yield</code><strong>?</strong> [#q-14bee738d69b814c8a60ec09d63210d0]

<strong>Оператор</strong> <code>yield</code> используется для упрощения создания
итераторов в C#. Он позволяет возвращать элементы по одному, сохраняя текущее
состояние выполнения метода, чтобы при следующем вызове продолжить с этого
места.

#### Основные функции&#58;

{/* prettier-ignore */}
1. <code>yield return</code>&#58;

    - Возвращает один элемент последовательности и сохраняет текущее положение метода.

    - Пример&#58;

        ```csharp
        public IEnumerable<int> GetNumbers()
        {
            yield return 1;
            yield return 2;
            yield return 3;
        }
        ```

1. <code>yield break</code>&#58;

    - Прерывает выполнение итератора и завершает генерацию последовательности.

    - Пример&#58;

        ```csharp
        public IEnumerable<int> GetNumbers(int limit)
        {
            for (int i = 0; i < limit; i++)
            {
                if (i > 5)
                    yield break;
                yield return i;
            }
        }
        ```

Оператор <code>yield</code> упрощает создание итераторов, позволяя возвращать элементы последовательности по одному (<code>yield return</code>) и прерывать генерацию последовательности (<code>yield break</code>).

:::note[Ссылки для изучения]

1. [Оператор yield](https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/statements/yield)
   :::

---

## <strong>Что такое рефлексия?</strong> [#q-14bee738d69b81debb94e1bb3d837ad4]

Рефлексия (<code>Reflection</code>) – это механизм в .NET, позволяющий программе исследовать и взаимодействовать с собственной структурой и метаданными во время выполнения.

<strong>Возможности&#58;</strong>

{/* prettier-ignore */}
1. <strong>Получение информации о типах&#58;</strong>

    - Исследование типов, методов, свойств, полей и других членов классов.

1. <strong>Создание экземпляров типов&#58;</strong>

    - Динамическое создание объектов и вызов конструкторов.

1. <strong>Вызов методов&#58;</strong>

    - Динамическое выполнение методов и доступ к их параметрам и возвращаемым значениям.

1. <strong>Доступ к полям и свойствам&#58;</strong>

    - Чтение и изменение значений полей и свойств объектов.

<strong>Пример использования рефлексии в C#&#58;</strong>

```csharp
using System;
using System.Reflection;

public class Example
{
    public int Number { get; set; }

    public void PrintNumber()
    {
        Console.WriteLine($"Number: {Number}");
    }
}

class Program
{
    static void Main()
    {
        // Получение типа
        Type type = typeof(Example);

        // Создание экземпляра
        object instance = Activator.CreateInstance(type);

        // Установка значения свойства
        PropertyInfo property = type.GetProperty("Number");
        property.SetValue(instance, 42);

        // Вызов метода
        MethodInfo method = type.GetMethod("PrintNumber");
        method.Invoke(instance, null);
    }
}
```

Рефлексия позволяет динамически исследовать и взаимодействовать с типами во время выполнения, предоставляя гибкость и мощные возможности для разработки. Однако, следует использовать её осторожно, так как она может влиять на производительность и безопасность приложения.

:::note[Ссылки для изучения]

1. [Рефлексия в .NET](https://learn.microsoft.com/en-us/dotnet/fundamentals/reflection/reflection)
   :::

---

## <strong>Расскажите о коллекции</strong> <code>LinkedList &#60;T&#62;</code><strong>. Чем она отличается от других коллекций?</strong> [#q-14bee738d69b81a2b7d1fa31f842731e]

<code>LinkedList&#60;T&#62;</code> – это двусвязный список, где каждый элемент
содержит ссылку на следующий и предыдущий элементы.

<strong>Особенности&#58;</strong>

{/* prettier-ignore */}
1. <strong>Двусвязный список&#58;</strong>

    - Каждый элемент (<code>LinkedListNode&#60;T&#62;</code>) содержит ссылки на следующий и предыдущий элементы.

    - Позволяет легко добавлять или удалять элементы в любом месте списка.

1. <strong>Быстрая вставка и удаление&#58;</strong>

    - Вставка и удаление элементов выполняются за постоянное время O(1), если известно местоположение узла.

    - Более эффективен при частых операциях вставки и удаления по сравнению с массивами.

1. <strong>Нет доступа по индексу&#58;</strong>

    - В отличие от массивов и списков (<code>List&#60;T&#62;</code>), доступ по индексу невозможен.

    - Для доступа к элементам требуется последовательный перебор от начала или конца списка.

<strong>Пример использования</strong> <code>LinkedList&#60;T&#62;</code>
<strong>в C#&#58;</strong>

```csharp
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // Создание LinkedList
        LinkedList<int> linkedList = new LinkedList<int>();

        // Добавление элементов
        linkedList.AddLast(1);
        linkedList.AddLast(2);
        linkedList.AddLast(3);

        // Вставка элемента в начало
        linkedList.AddFirst(0);

        // Вставка элемента после первого узла
        LinkedListNode<int> node = linkedList.First;
        linkedList.AddAfter(node, 10);

        // Перебор элементов
        foreach (var item in linkedList)
        {
            Console.WriteLine(item);
        }

        // Удаление элемента
        linkedList.Remove(10);
    }
}
```

<code>LinkedList&#60;T&#62;</code> отличается от других коллекций тем, что
позволяет быстро добавлять и удалять элементы в любом месте списка. Однако,
доступ к элементам осуществляется через последовательный перебор, что может быть
менее эффективно по сравнению с коллекциями, поддерживающими доступ по индексу.

:::note[Ссылки для изучения]

1. [LinkedList &#60;T&#62; в .NET](https://learn.microsoft.com/ru-ru/dotnet/api/system.collections.generic.linkedlist-1?view=net-8.0)
   :::

---

## <strong>Что такое индексатор?</strong> [#q-14bee738d69b818f9446e013dd495d8a]

Индексатор (<code>Indexer</code>) – это специальный элемент в C#, который позволяет экземпляру класса или структуры быть индексированным так же, как массив.

<strong>Возможности&#58;</strong>

{/* prettier-ignore */}
1. <strong>Упрощенный доступ к данным&#58;</strong>

    - Предоставляет возможность доступа к элементам класса или структуры с использованием синтаксиса индексирования, аналогичного массивам.

1. <strong>Определение логики доступа&#58;</strong>

    - Позволяет реализовать пользовательскую логику для доступа к данным и их модификации.

1. <strong>Поддержка нескольких параметров&#58;</strong>

    - Можно использовать несколько параметров для индексирования, что полезно для сложных структур данных.

<strong>Пример использования индексатора в C#&#58;</strong>

```csharp
using System;

public class SampleCollection<T>
{
    private T[] arr = new T[100];

    public T this[int index]
    {
        get { return arr[index]; }
        set { arr[index] = value; }
    }
}

class Program
{
    static void Main()
    {
        SampleCollection<string> stringCollection = new SampleCollection<string>();
        stringCollection[0] = "Hello, World!";
        Console.WriteLine(stringCollection[0]);
    }
}
```

Индексаторы позволяют упростить доступ к внутренним данным класса или структуры, делая код более читаемым и удобным для использования.

:::note[Ссылки для изучения]

1. [Обзор индексаторов в .NET](https://learn.microsoft.com/ru-ru/dotnet/csharp/indexers)
   :::

---

## <strong>Когда использовать</strong> <code>StringBuilder</code><strong>, а когда</strong> <code>string</code><strong>? Как работает</strong> <code>StringBuilder</code><strong>?</strong> [#q-14bee738d69b81198835ee45e01a89df]

<code>StringBuilder</code> – это класс в .NET, предназначенный для работы с
изменяемыми строками, что делает его более эффективным для частых операций
изменения строк.

<strong>Когда использовать</strong> <code>StringBuilder</code>
<strong>&#58;</strong>

{/* prettier-ignore */}
1. <strong>Многочисленные изменения строк&#58;</strong>

    - Если строка часто изменяется в цикле или в процессе выполнения программы (например, конкатенация, вставка, удаление).

1. <strong>Оптимизация производительности&#58;</strong>

    - Для операций, где производительность критична, и требуется избежать создания большого количества промежуточных строк.

<strong>Когда использовать</strong> <code>string</code>
<strong>&#58;</strong>

{/* prettier-ignore */}
1. <strong>Небольшие или неизменяемые строки&#58;</strong>

    - Для строк, которые не требуют частых изменений.

1. <strong>Литералы и краткие операции&#58;</strong>

    - Для небольших операций конкатенации или использования строковых литералов.

<strong>Как работает</strong> <code>StringBuilder</code>
<strong>&#58;</strong>

{/* prettier-ignore */}
- <strong>Изменяемость&#58;</strong>

    - StringBuilder изменяет внутренние буферы и уменьшает число промежуточных строк. Рост буфера может выделять память, а ToString() создает итоговую строку.

- <strong>Буферизация&#58;</strong>

    - Изначально создается буфер определенного размера, который автоматически увеличивается по мере необходимости.

- <strong>Методы&#58;</strong>

    - Методы StringBuilder, такие как <code>Append</code>, <code>Insert</code>, <code>Remove</code>, <code>Replace</code>, изменяют содержимое буфера непосредственно, что повышает эффективность.

<strong>Пример использования</strong> <code>StringBuilder</code>
<strong>в C#&#58;</strong>

```csharp
using System;
using System.Text;

class Program
{
    static void Main()
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("Hello");
        sb.Append(", ");
        sb.Append("World!");

        Console.WriteLine(sb.ToString()); // Вывод: Hello, World!
    }
}
```

<code>StringBuilder</code> следует использовать для операций, требующих частого
изменения строк, чтобы улучшить производительность и избежать создания множества
временных объектов. Для небольших или неизменяемых строк лучше использовать
<code>string</code>.

:::note[Ссылки для изучения]

1. [Оператор yield](https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/statements/yield)
   :::

---

## <strong>Что такое балансирование деревьев?</strong> [#q-14bee738d69b810da264f87d2d6d70a2]

Балансирование деревьев (<code>Tree Balancing</code>) – это процесс изменения структуры дерева, чтобы поддерживать его сбалансированное состояние, что обеспечивает равномерное распределение узлов и минимальную высоту дерева.

<strong>Возможности&#58;</strong>

{/* prettier-ignore */}
1. <strong>Поддержание равномерной высоты&#58;</strong>

    - Поддерживает высоту O(log n) при соблюдении инвариантов выбранного дерева; минимально возможная высота не гарантируется.

1. <strong>Оптимизация операций&#58;</strong>

    - Уменьшает время выполнения операций поиска, вставки и удаления до O(log n) в среднем случае.

<strong>Основные методы балансировки деревьев&#58;</strong>

{/* prettier-ignore */}
1. <code>AVL</code><strong>-деревья&#58;</strong>

    - Дерево, в котором для любого узла высота его левого и правого поддеревьев отличается не более чем на 1.

    - При вставке и удалении узлов выполняются вращения для поддержания этого свойства.

1. <strong>Красно-черные деревья&#58;</strong>

    - Двоичное дерево поиска, в котором каждый узел имеет цвет (красный или черный) и соблюдаются определенные правила, чтобы дерево оставалось сбалансированным.

    - На всех путях от одного узла до его NIL-листьев одинаковое число черных узлов; два красных узла не могут идти подряд. Поэтому самый длинный такой путь не более чем вдвое длиннее самого короткого.

1. <code>B</code><strong>-деревья&#58;</strong>

    - Сбалансированные деревья, которые позволяют узлам иметь более одного дочернего узла. Широко используются в базах данных и файловых системах для обеспечения сбалансированности и эффективного доступа к данным.

<strong>Пример балансировки</strong> <code>AVL</code>
<strong>-дерева&#58;</strong>

```csharp
public class AVLTree
{
    public class Node
    {
        public int Value;
        public Node Left;
        public Node Right;
        public int Height;

        public Node(int value)
        {
            Value = value;
            Height = 1;
        }
    }

    public Node Root;

    // Вставка и балансировка
    public Node Insert(Node node, int value)
    {
        if (node == null)
            return new Node(value);

        if (value < node.Value)
            node.Left = Insert(node.Left, value);
        else if (value > node.Value)
            node.Right = Insert(node.Right, value);
        else
            return node;

        node.Height = 1 + Math.Max(Height(node.Left), Height(node.Right));
        return Balance(node);
    }

    // Высота узла
    private int Height(Node node) => node?.Height ?? 0;

    // Балансировка узла
    private Node Balance(Node node)
    {
        int balance = Height(node.Left) - Height(node.Right);
        if (balance > 1)
        {
            if (Height(node.Left.Left) >= Height(node.Left.Right))
                node = RotateRight(node);
            else
                node = RotateLeftRight(node);
        }
        else if (balance < -1)
        {
            if (Height(node.Right.Right) >= Height(node.Right.Left))
                node = RotateLeft(node);
            else
                node = RotateRightLeft(node);
        }
        return node;
    }

    // Правое вращение
    private Node RotateRight(Node y)
    {
        Node x = y.Left;
        y.Left = x.Right;
        x.Right = y;
        y.Height = Math.Max(Height(y.Left), Height(y.Right)) + 1;
        x.Height = Math.Max(Height(x.Left), Height(x.Right)) + 1;
        return x;
    }

    // Левое вращение
    private Node RotateLeft(Node x)
    {
        Node y = x.Right;
        x.Right = y.Left;
        y.Left = x;
        x.Height = Math.Max(Height(x.Left), Height(x.Right)) + 1;
        y.Height = Math.Max(Height(y.Left), Height(y.Right)) + 1;
        return y;
    }

    // Левое-правое вращение
    private Node RotateLeftRight(Node node)
    {
        node.Left = RotateLeft(node.Left);
        return RotateRight(node);
    }

    // Правое-левое вращение
    private Node RotateRightLeft(Node node)
    {
        node.Right = RotateRight(node.Right);
        return RotateLeft(node);
    }
}
```

Балансирование деревьев обеспечивает равномерное распределение узлов и минимальную высоту дерева, что улучшает производительность операций поиска, вставки и удаления. Различные методы балансировки, такие как AVL-деревья, красно-черные деревья и B-деревья, используются для поддержания сбалансированного состояния деревьев.

:::note[Ссылки для изучения]

1. [Балансировка деревьев](https://ru.hexlet.io/courses/algorithms-trees/lessons/balancing/theory_unit)
   :::

---

## <strong>Что такое</strong> <code>Key&#45;value</code> <strong>структуры?</strong> [#q-14bee738d69b81aa8054dd4ba7b52513]

<code>Key&#45;value</code> структуры – это тип структуры данных, где данные
хранятся в виде пар "ключ-значение". Каждое значение ассоциировано с уникальным
ключом, который используется для доступа к этому значению.

<strong>Возможности&#58;</strong>

{/* prettier-ignore */}
1. <strong>Быстрый доступ к данным&#58;</strong>

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

1. <strong>Простота структуры&#58;</strong>

    - Простая и гибкая структура, позволяющая хранить любые данные без сложных схем.

1. <strong>Широкое применение&#58;</strong>

    - Используются в кэшировании, базах данных, конфигурационных хранилищах и распределенных системах.

<strong>Использование</strong> <code>Dictionary&#60;TKey&#44; TValue&#62;</code>
<strong>&#58;</strong>

```csharp
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // Создание словаря
        Dictionary<string, int> ageDictionary = new Dictionary<string, int>();

        // Добавление пар ключ-значение
        ageDictionary["Alice"] = 30;
        ageDictionary["Bob"] = 25;

        // Получение значения по ключу
        if (ageDictionary.TryGetValue("Alice", out int age))
        {
            Console.WriteLine($"Alice is {age} years old.");
        }
    }
}
```

<strong>Использование</strong> <code>Hashtable</code>
<strong>&#58;</strong>

```csharp
using System;
using System.Collections;

class Program
{
    static void Main()
    {
        // Создание Hashtable
        Hashtable hashtable = new Hashtable();

        // Добавление пар ключ-значение
        hashtable["Alice"] = 30;
        hashtable["Bob"] = 25;

        // Получение значения по ключу
        if (hashtable.ContainsKey("Alice"))
        {
            Console.WriteLine($"Alice is {hashtable["Alice"]} years old.");
        }
    }
}
```

<code>Key&#45;value</code> структуры предоставляют простой и эффективный способ
хранения и доступа к данным через уникальные ключи, обеспечивая высокую
производительность и гибкость. Они широко используются в различных областях
программирования, от кэширования до баз данных.

:::note[Ссылки для изучения]

1. [Структура KeyValuePair](https://learn.microsoft.com/ru-ru/dotnet/api/system.collections.generic.keyvaluepair-2?view=net-8.0)
   :::

---

## <strong>Что такое хэш-функция и зачем нужны хэш-таблицы?</strong> [#q-14bee738d69b8117b3dcd1ad89f7ed90]

Хэш-функция (<code>Hash Function</code>) – это функция, которая преобразует входные данные произвольного размера в фиксированный размер, обычно представленный числом.

<strong>Возможности&#58;</strong>

{/* prettier-ignore */}
1. <strong>Быстрое вычисление&#58;</strong>

    - Хэш-функции должны быть быстрыми для вычисления хэш-кода.

1. <strong>Распределение&#58;</strong>

    - Хорошая хэш-функция равномерно распределяет значения, чтобы минимизировать коллизии.

1. <strong>Детерминированность&#58;</strong>

    - Одинаковые входные данные всегда дают одинаковый хэш-код.

<strong>Примеры хэш-функций&#58;</strong>

- SHA-256 — пример криптографической хеш-функции. MD5 устарел для задач, требующих стойкости к коллизиям; обычный GetHashCode не предназначен для криптографической защиты.

- Простые математические функции для хэш-таблиц.

#### Хэш-таблицы

Хэш-таблицы (<code>Hash Tables</code>) – это структуры данных, которые используют хэш-функции для сопоставления ключей с их значениями.

<strong>Возможности&#58;</strong>

{/* prettier-ignore */}
1. <strong>Быстрый доступ&#58;</strong>

    - Обеспечивают время доступа к элементам в среднем O(1).

1. <strong>Коллизии&#58;</strong>

    - Решают проблемы коллизий с помощью цепочек (linked lists) или открытой адресации.

1. <strong>Эффективное использование памяти&#58;</strong>

    - Хорошо подходят для больших наборов данных, где необходим быстрый доступ по ключу.

<strong>Пример использования хэш-таблицы в C#&#58;</strong>

```csharp
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // Создание словаря (хэш-таблицы)
        Dictionary<string, int> hashTable = new Dictionary<string, int>();

        // Добавление пар ключ-значение
        hashTable["Alice"] = 30;
        hashTable["Bob"] = 25;

        // Получение значения по ключу
        if (hashTable.TryGetValue("Alice", out int age))
        {
            Console.WriteLine($"Alice is {age} years old.");
        }
    }
}
```

:::note[Ссылки для изучения]

1. [Как работает хэширование](https://habr.com/ru/companies/ruvds/articles/747084/)
   :::

---

## <strong>Какими свойствами должна обладать идеальная хеш-функция?</strong> [#q-14bee738d69b81ac9fb8d44a4a0e68b4]

Идеальная хэш-функция должна обладать следующими свойствами&#58;

{/* prettier-ignore */}
1. <strong>Быстрота вычисления&#58;</strong>

    - Хэш-код должен вычисляться быстро, чтобы обеспечивать высокую производительность.

1. <strong>Равномерное распределение&#58;</strong>

    - Хэш-коды должны быть равномерно распределены по возможным значениям, чтобы минимизировать коллизии.

1. <strong>Детерминированность&#58;</strong>

    - Одинаковые входные данные всегда должны давать одинаковый хэш-код.

1. <strong>Минимизация коллизий&#58;</strong>

    - Разные входные данные должны с большой вероятностью давать разные хэш-коды.

1. <strong>Аваланш-эффект&#58;</strong>

    - Небольшое изменение во входных данных должно приводить к значительному изменению хэш-кода.

:::note[Ссылки для изучения]

1. [Что такое хеш-функция и как её выбрать](https://www.geeksforgeeks.org/what-are-hash-functions-and-how-to-choose-a-good-hash-function/)
   :::

---

## <strong>Что такое коллизии в хешировании и как с ними бороться?</strong> [#q-14bee738d69b81b4a9a8cde491fe4c0c]

Коллизия происходит, когда две разные входные данные дают одинаковый хэш-код.

#### Методы борьбы с коллизиями&#58;

{/* prettier-ignore */}
1. <strong>Метод цепочек (</strong><code>Chaining</code><strong>)&#58;</strong>

    - <strong>Описание&#58;</strong> Каждый элемент хэш-таблицы содержит указатель на список всех элементов, имеющих одинаковый хэш-код.

    - <strong>Преимущества&#58;</strong> Простота реализации, динамическое управление коллизиями.

    - <strong>Пример&#58;</strong>

        ```csharp
        Dictionary<int, List<string>> hashTable = new Dictionary<int, List<string>>();
        ```

1. <strong>Открытая адресация (Open</strong> <code>Addressing</code><strong>)&#58;</strong>

    - <strong>Описание&#58;</strong> В случае коллизии ищется следующая свободная ячейка по определенному алгоритму (линейное пробирование, квадратичное пробирование, двойное хеширование).

    - <strong>Преимущества&#58;</strong> Все элементы хранятся в самой хэш-таблице, отсутствуют дополнительные структуры.

    - <strong>Пример&#58;</strong>

        ```csharp
        int LinearProbing(int hash, int i, int size) => (hash + i) % size;
        ```

1. <strong>Перехеширование (</strong><code>Rehashing</code><strong>)&#58;</strong>

    - <strong>Описание&#58;</strong> При переполнении или достижении определенного уровня заполненности хэш-таблица увеличивается в размере, и все элементы перехешируются.

    - <strong>Преимущества&#58;</strong> Улучшает распределение элементов, снижает вероятность коллизий.

    - <strong>Пример&#58;</strong>

        ```csharp
        void Rehash(Dictionary<int, string> oldTable)
        {
            // Создание новой таблицы большего размера и перераспределение элементов
        }
        ```

Коллизии неизбежны в хешировании, но их можно эффективно управлять с помощью методов цепочек, открытой адресации и перехеширования, обеспечивая надежность и производительность хэш-таблиц.

:::note[Ссылки для изучения]

1. [Что нужно знать об устройстве коллекций, основанные на хешировании](https://habr.com/ru/companies/otus/articles/495032/)
   :::

---

## <strong>В чем разница между</strong> <code>IEnumerable</code> <strong>и</strong> <code>IQueryable</code><strong>?</strong> [#q-14bee738d69b81d5bb64e78430128fd0]

<code>IEnumerable&#60;T&#62;</code> и <code>IQueryable&#60;T&#62;</code> — это
два интерфейса в .NET для работы с коллекциями данных, но они имеют разные цели
и используются в различных сценариях.

#### <code>IEnumerable&#60;T&#62;</code>&#58;

<strong>Определение&#58;</strong>

- Представляет последовательность элементов, доступных для перебора.

<strong>Основные характеристики&#58;</strong>

{/* prettier-ignore */}
1. <strong>Отложенное выполнение&#58;</strong>

    - Методы, такие как <code>Where</code>, <code>Select</code>, вызываются, но не выполняются до начала перебора коллекции.

1. <strong>Работа в памяти&#58;</strong>

    - Поддерживает перебор данных в памяти.

1. <strong>Использование&#58;</strong>

    - Подходит для работы с данными, уже загруженными в память.

1. <strong>Пример&#58;</strong>

    ```csharp
    IEnumerable<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
    var evenNumbers = numbers.Where(n => n % 2 == 0);
    foreach (var num in evenNumbers)
    {
        Console.WriteLine(num);
    }
    ```

#### <code>IQueryable&#60;T&#62;</code>&#58;

<strong>Определение&#58;</strong>

- Представляет запрос, который может быть выполнен на удаленном источнике данных, как правило, базе данных.

<strong>Основные характеристики&#58;</strong>

{/* prettier-ignore */}
1. <strong>Отложенное выполнение&#58;</strong>

    - Запрос формируется, но не выполняется до начала перебора коллекции или вызова метода, такого как <code>ToList</code>.

1. <strong>Использование провайдера запросов&#58;</strong>

    - Запросы могут быть преобразованы в соответствующий язык запросов (например, SQL для базы данных).

1. <strong>Оптимизация запросов&#58;</strong>

    - Позволяет выполнять оптимизированные запросы на удаленных источниках данных, таких как базы данных.

1. <strong>Пример&#58;</strong>

    ```csharp
    IQueryable<int> numbers = dbContext.Numbers;
    var evenNumbers = numbers.Where(n => n % 2 == 0);
    foreach (var num in evenNumbers)
    {
        Console.WriteLine(num);
    }
    ```

#### Итог&#58;

- IEnumerable&#60;T&#62; задает перебор последовательности, которая может получать данные лениво, в том числе из внешнего источника. IQueryable&#60;T&#62; дополнительно хранит дерево выражений и провайдер запросов; удаленная БД не обязательна.

- <code>IQueryable&#60;T&#62;</code>
  <strong>&#58;</strong> Используется для работы с удаленными источниками
  данных, обеспечивая оптимизированные запросы и отложенное выполнение.

:::note[Ссылки для изучения]

1. [Разница между IEnumerable и IQueryable](https://stackoverflow.com/questions/252785/what-is-the-difference-between-iqueryablet-and-ienumerablet.#:~:text=%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%BE%D0%B5%20%D1%80%D0%B0%D0%B7%D0%BB%D0%B8%D1%87%D0%B8%D0%B5%20%D0%BC%D0%B5%D0%B6%D0%B4%D1%83%20IQueryable%20%D0%B8,%D1%84%D0%B8%D0%BB%D1%8C%D1%82%D1%80%D1%83%D0%B5%D1%82%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5%20%D0%BD%D0%B0%20%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B5%20%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D0%B9)
   :::
