.NET Разработчик
6.52K subscribers
441 photos
3 videos
14 files
2.12K links
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 1247. #Карьера #ВопросыНаСобеседовании
Самые Распространённые Вопросы на Поведенческом Собеседовании. Начало
Вот топ вопросов на поведенческом собеседовании, на которые вы должны быть готовы ответить при приёме на работу.

Что это такое?
Поведенческие вопросы предназначены для того, чтобы определить, как вы будете справляться с конкретными ситуациями в рабочей среде. Часто вас просят использовать свой опыт в качестве примера и больше сосредоточиться на социальных навыках, а не на технических аспектах работы. Это позволяет потенциальному работодателю понять, как ваш прошлый опыт работы подготовил вас к будущим задачам и вызовам. Наверняка вас просили ответить на вопрос вроде: «Расскажите о случае, когда у вас был конфликт с кем-то из вашей команды».

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

1. «Какая у вас самая большая слабость?»
Один из самых распространённых вопросов, и тот, на котором чаще всего спотыкаются. Лучший ответ — назвать слабость, которая применима только к конкретным ситуациям, например: «Не терплю, когда коллеги не выполняют обещания, особенно когда это относится к критически важным задачам». Ключ в том, чтобы закончить ответ тем, как вы планируете избавиться от этой слабости. Это яркий пример того, как использовать метод STAR (Situation, Task, Action, Result - Ситуация, Задача, Действие, Результат).

Ситуация: опишите ситуацию, в которой всё произошло.
Задача: опишите задачу, которую вы должны были выполнить, чтобы решить проблему.
Действие: объясните, какие действия вы предприняли для выполнения задачи.
Результат: расскажите о результатах своих действий и постарайтесь быть как можно более подробным. Как ваши действия помогли компании или организации работать лучше?

2. Вопросы о командной работе
Большинство профессий требуют, чтобы вы работали в команде, поэтому будьте готовы рассказать о своём опыте как члена команды. Вам понадобится история, показывающая вашу способность работать с другими в трудных обстоятельствах. Подумайте о разрешении конфликтов в команде, преодолении ограничений проекта или мотивации других.

«Расскажите о ситуации, когда вам пришлось сотрудничать с кем-то, чей характер сильно отличался от вашего.»
«Опишите ситуацию, когда вам пришлось проявить инициативу и продемонстрировать лидерские качества.»
«Расскажите о случае, когда вам нужно было получить информацию от человека, который не очень реагировал. Что вы сделали?»
«Расскажите о случае, когда вы неверно отреагировали на ситуацию с коллегой.»

Вопросы о командной работе — отличный шанс указать на вашу способность к сотрудничеству, и ваш ответ должен подчеркнуть ваши сильные стороны в этой области. Может быть трудно представить конфликт как положительный момент, особенно если вы чувствуете, что были не неправы. Важно помнить, что в ответе нужно сосредоточиться не на конфликте, а на процессе поиска решения.

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

Продолжение следует…

Источник:
https://www.fastcompany.com/90756503/your-ultimate-guide-to-ace-the-most-common-interview-questions
👍4
День 1248. #Карьера #ВопросыНаСобеседовании
Самые Распространённые Вопросы на Поведенческом Собеседовании. Продолжение
Начало

3. Вопросы про клиентов
Если работа требует, чтобы вы работали с клиентами или партнёрами, подготовьтесь к некоторым из таких вопросов. Работодатели захотят понять, как вы положительно представили компанию и как вы преодолели трудности, чтобы лучше обслужить клиента.

«Опишите ситуацию взаимодействия с трудным клиентом и как вы с ней справились.»
«Как вы расставляете приоритеты, когда работаете с большим количеством запросов от клиентов.»
«Случалось ли, что вы не оправдали ожиданий клиента, и как вы пытались исправить ситуацию.»

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

Не всем вашим историям нужен счастливый конец, но акцентируйте внимание на том, какой опыт вы получили, независимо от результата.

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

«Расскажите о случае завала на работе. Что вы сделали?»
«Расскажите о случае, когда непредвиденная проблема сорвала ваши планы. Как вы отреагировали?»
«Как вы ставите цели и как добиваетесь их достижения?»

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

5. Вопросы о ваших коммуникативных способностях
Вы должны уметь чётко и уважительно излагать свои мысли. Большинство людей смогут привести примеры коммуникации, но главное здесь — рассказать историю, в которой подчёркивается вдумчивая подготовка и логический мыслительный процесс.

«Расскажите об успешной презентации, которую вы провели, и почему вы считаете её успешной.»
«Расскажите о ситуации, когда вам приходилось полагаться на письменное общение, чтобы объяснить свои идеи вашей команде.»
«Приведите пример, когда вам удалось убедить коллегу в вашей правоте.»

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

Окончание следует…

Источник:
https://www.fastcompany.com/90756503/your-ultimate-guide-to-ace-the-most-common-interview-questions
👍6
День 1249. #Карьера #ВопросыНаСобеседовании
Самые Распространённые Вопросы на Поведенческом Собеседовании. Окончание
Начало
Продолжение

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

«Расскажите о случае, когда вы находились под сильным давлением и как вы это пережили.»
«Расскажите, как вы устроились на предыдущую работу и адаптировались там.»
«Расскажите о вашей неудаче. Как вы справились с ситуацией?»

Используйте вопросы об адаптации, чтобы рассказать о:
- том, как вы ставите цели и придерживаетесь их;
- методах борьбы со стрессом, которые используете.

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

7. Вопросы и мотивации и ценностях
Иногда вопросы интервью могут показаться случайными или личными. Многие из них — это попытки узнать больше о том, что вас мотивирует. В идеале ваш ответ должен напрямую касаться ценностей и мотивации, даже если в вопросе о них прямо не говорится.

«Расскажите о своём самом большом профессиональном достижении.»
«Расскажите о случае, когда вы работали либо под очень пристальным надзором, либо под очень слабым надзором. Как вы с этим справились?»
«Приведите пример, когда вы смогли проявить творческий подход в работе. Что было интересным или трудным в этом?»
«Расскажите о случае, когда вы были недовольны своей ролью. Что можно было сделать?»

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

Для начала расскажите о том, как недавно повысили свой профессиональный уровень. Это простой способ показать, что вы не только мотивированы на совершенствование, но и активно работаете над этим.

Итого
Существует бесконечное количество способов ответить на вопросы поведенческого интервью. Самое главное, что нужно помнить:
1) Будьте честным.
2) Заранее изучите возможные вопросы.
3) Запишите кратко истории, которые, по вашему мнению, будут хорошими ответами на вопросы.
4) Запишите опыт, который вы извлекли из каждой истории.

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

Источник: https://www.fastcompany.com/90756503/your-ultimate-guide-to-ace-the-most-common-interview-questions
👍3👎1
День 1355. #Карьера #ВопросыНаСобеседовании
Что Отвечать на Вопрос о Зарплатных Ожиданиях
Наткнулся на интересное видео «Пример лучшего ответа на вопрос о ваших зарплатных ожиданиях». Автор представляет дословный скрипт, куда нужно подставить только цифры. Это мне показалось интересным, поэтому решил «локализовать» для нашей части света.

Для начала несколько советов.
1. Изучите диапазон средних зарплат на вашу должность перед тем, как пойдёте на собеседование.
Данные можно взять, например с Хабр.Карьеры (для РФ) или DOU (для Украины). Добавьте в комментариях, если знаете другие источники.

2. Просите зарплату слегка ниже верхнего предела.
К примеру, если средняя ЗП на уровень мидл разработчика находится в диапазоне от $2000 до $3500, просите $3200.

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

Теперь собственно скрипт:
«Перед тем, как пойти на собеседование я исследовал средние зарплаты по рынку на эту должность. Средние зарплаты колеблются от $2000 до $3500. Несмотря на то, что я хотел бы получать больше, я понимаю, что вы меня не знаете, а мне ещё нужно доказать, что я достоин зарабатывать такие деньги. Учитывая это, комфортным для меня уровнем будет $3200, и я уверен, что моё трудолюбие, ответственность, исполнительность и способность быстро вникать в рабочие процессы докажут вам, что я стою потраченных на меня денег.»

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

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

Источник: https://youtu.be/0k13HVHJoNc
👍8
День 1647. #ВопросыНаСобеседовании
Самые часто задаваемые вопросы на собеседовании по C#
Давненько не было ничего из этой рубрики. Нумерацию продолжу, если что, предыдущие вопросы доступны по тегу #ВопросыНаСобеседовании.

19. В чем разница между интерфейсами IEnumerable, ICollection и IList в C#?
IEnumerable, ICollection и IList — это интерфейсы, предоставляемые библиотеками платформы .NET для работы с коллекциями данных. Они имеют следующие особенности.

IEnumerable:
- Предоставляет базовые функции для итерации по коллекции с использованием цикла foreach.
- Поддерживает доступ только для чтения.
- Идеально подходит для ситуаций, когда вам нужно только перебирать коллекцию.
- Определяет только один метод: GetEnumerator(), который возвращает IEnumerator.

ICollection:
- Наследуется от IEnumerable.
- Представляет собой группу элементов с дополнительными функциями, такими как размер (свойство Count), перечисление и синхронизация (через свойства IsSynchronized и SyncRoot).
- Добавляет основные операции с коллекцией, такие как Add, Remove, Clear, проверку вхождения элемента (Contains) или проверку списка на доступность записи IsReadOnly.
- Поддерживает доступ как для чтения, так и для записи.

IList:
- Наследуется от ICollection.
- Представляет список элементов, доступных по индексу.
- Предоставляет расширенные возможности управления коллекцией, такие как вставка и удаление по индексу (методы Insert и RemoveAt).
- Поддерживает произвольный доступ к элементам через индексатор.

См. также
- «В чём разница между IEnumerable и IQueryable?»
- «Какой Интерфейс Коллекции Использовать?»

Источник: https://dev.to/bytehide/20-c-interview-questions-for-experienced-2023-1hl6
👍25
День 1658. #ВопросыНаСобеседовании
Самые часто задаваемые вопросы на собеседовании по C#

20. Какие типы делегатов существуют в C#?

Делегаты в C# можно разделить на три основных типа:
1) Обычные
Ссылаются на один метод с соответствующей сигнатурой. Когда делегат вызывается, он вызывает указанный метод.
public delegate void DisplayMessage(string message);

DisplayMessage display = ShowMessage;
display("Hello, delegate!");

void ShowMessage(string message)
=> Console.WriteLine(message);

2) Многоадресные (Multicast)
Могут ссылаться на несколько методов с совпадающей сигнатурой. Когда делегат вызывается, он вызывает все указанные методы в том порядке, в котором они были добавлены. Многоадресные делегаты создаются из обычных с помощью операторов += или -=.
DisplayMessage display = ShowMessage1;
display += ShowMessage2;
display("Hello, Multicast delegate!");

void ShowMessage1(string msg)
=> Console.WriteLine($"Message 1: {msg}");
void ShowMessage2(string msg)
=> Console.WriteLine($"Message 2: {msg}");

3) Обобщённые
Используют параметры типа, что позволяет им работать с несколькими типами без приведения или упаковки/распаковки. C# предоставляет три встроенных обобщённых делегата: Func, Action и Predicate.
- Func<TResult>: представляет функцию с возвращаемым типом.
- Action: представляет метод, возвращающий void, без параметров.
- Predicate<T>: представляет метод, который принимает входной параметр и возвращает логическое значение.
Func и Action имеют перегрузки, принимающие большее количество аргументов.

Func<int, int, int> add = 
(x, y) => x + y;
int sum = add(10, 20);

Action<string> display =
msg => Console.WriteLine(msg);
display($"Sum: {sum}");

Predicate<string> startsWithHello =
x => x.StartsWith("Hello, ");
bool checkHello = startsWithHello("Hello, delegate");

См. также:
- Управление цепочками делегатов
- Анонимные методы
- Лямбда-выражения

Источник: https://dev.to/bytehide/20-c-interview-questions-for-experienced-2023-1hl6
👍28
День 1666. #ВопросыНаСобеседовании
Самые часто задаваемые вопросы на собеседовании по C#

21. Что такое слабые ссылки и когда их использовать в C#?
В C# слабые ссылки — это ссылки на объекты, которые недостаточно надёжны, чтобы предотвратить сборку мусора для этих объектов. Они позволяют поддерживать ссылку на объект до тех пор, пока объект жив в памяти, но не препятствуя сборщику мусора (GC) освобождать объект при увеличении нагрузки на память. Со слабыми ссылками вы можете получить доступ к объекту, пока он всё ещё находится в памяти, но это не помешает GC удалить объект, если это необходимо.

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

Чтобы использовать слабую ссылку в C#, создайте экземпляр класса WeakReference или WeakReference<T>:
WeakReference<MyLargeObject> wr 
= new(new MyLargeObject());

MyLargeObject lo;
if (wr.TryGetTarget(out largeObject))
{
// объект всё ещё в памяти, используем его
Console.WriteLine("Используем объект.");
}
else
{
// объект удалён сборщиком мусора
Console.WriteLine("Объект удалён.");
largeObject = new MyLargeObject();
}

class MyLargeObject
{
private byte[] _data = new byte[1000000];
}

В этом примере, если GC решит освободить память, используемую экземпляром MyLargeObject, вызов weakReference.TryGetTarget возвратит значение false. В противном случае largeObject останется доступным через слабую ссылку.

Источник: https://dev.to/bytehide/20-senior-developer-c-interview-questions-and-answers-2023-3bjc
👍42
День 1687. #ВопросыНаСобеседовании #Многопоточность
Самые часто задаваемые вопросы на собеседовании по C#

22. В контексте многопоточности C# каковы основные различия между ThreadPool и созданием выделенных экземпляров Thread?

1. Управление ресурсами:
ThreadPool управляет пулом рабочих потоков, которые повторно используются для нескольких задач, сокращая накладные расходы на создание и уничтожение потоков. Непосредственное создание потоков создаёт новый поток для каждой задачи, что может быть ресурсоёмким, особенно при обработке большого количества задач.

2. Время жизни потока: потоки из ThreadPool имеют фоновый статус, и их время жизни управляется системой. Выделенные потоки по умолчанию имеют приоритетный статус, а их время существования контролируется разработчиком.

3. Масштабируемость: ThreadPool автоматически регулирует количество рабочих потоков в зависимости от загрузки системы и доступных ресурсов, обеспечивая лучшую масштабируемость приложений. При создании выделенных потоков вы должны самостоятельно управлять количеством потоков, что может быть более сложным и подверженным ошибкам.

4. Приоритет и настройка: потоки из ThreadPool имеют приоритет по умолчанию и ограниченную настройку. Выделенные потоки можно настраивать по приоритету, имени, размеру стека и другим свойствам.

5. Синхронизация: ThreadPool помогает с синхронизацией потоков, поскольку рабочие элементы ставятся в очередь и выполняются доступными потоками. При использовании выделенных потоков за синхронизацию потоков отвечают разработчики.

Пример использования ThreadPool:
ThreadPool.QueueUserWorkItem((_) =>
{
// Логика вашей задачи здесь
});

Пример выделенного потока:
var thread = new Thread(() =>
{
// Логика вашей задачи здесь
});
thread.Start();

Источник: https://dev.to/bytehide/c-multithreading-interview-questions-and-answers-4opj
👍10
День 1702. #ВопросыНаСобеседовании #Многопоточность
Самые часто задаваемые вопросы на собеседовании по C#

23. Как обеспечить взаимоисключающий доступ к общим ресурсам в многопоточной системе в C# без использования
lock или Monitor?

Вы можете использовать другие примитивы синхронизации. Некоторые распространенные альтернативы:
1) Мьютекс: гарантирует, что только один поток может одновременно получить доступ к общему ресурсу. В отличие от lock, мьютекс – примитив ОС и может обеспечивать межпроцессную синхронизацию. Пример:
var mutex = new Mutex();
//...
mutex.WaitOne();
try
{
// Доступ к общему ресурсу
}
finally
{
mutex.ReleaseMutex();
}

2) Семафор: ограничивает количество одновременных потоков, которые могут получить доступ к общему ресурсу. Пример:
var sem = new Semaphore(1, 1); 
// Начальное и максимальное количество
// потоков установлено в 1
//...
sem.WaitOne();
try
{
// Доступ к общему ресурсу
}
finally
{
sem.Release();
}

3) ReaderWriterLockSlim: обеспечивает эффективный доступ для чтения и записи к общим ресурсам. Позволяет выполнять несколько одновременных операций чтения, когда ни один писатель не удерживает блокировку на запись. Пример:
var rwLock = new ReaderWriterLockSlim();
//...
// Чтение
rwLock.EnterReadLock();
try
{
// Доступ к общему ресурсу
}
finally
{
rwLock.ExitReadLock();
}
//...
// Запись
rwLock.EnterWriteLock();
try
{
// Доступ к общему ресурсу
}
finally
{
rwLock.ExitWriteLock();
}

4) SpinLock: пытается получить блокировку до тех пор, пока не будет достигнут успех. SpinLock следует использовать в сценариях с низким уровнем конфликтов, когда ожидается, что блокировка будет удерживаться в течение очень короткого времени. Пример:
var spinLock = new SpinLock();
bool lockTaken = false;
//...
spinLock.Enter(ref lockTaken);
try
{
// Доступ к общему ресурсу
}
finally
{
if (lockTaken)
{
spinLock.Exit();
}
}

Помните, что эти примитивы синхронизации имеют более высокие накладные расходы чем обычный lock.

UPD: спасибо подписчикам, напомнили про прекрасный доклад о примитивах синхронизации от Станислава Сидристого.

Источник: https://dev.to/bytehide/c-multithreading-interview-questions-and-answers-4opj
👍17
День 1713. #ВопросыНаСобеседовании #Многопоточность
Самые часто задаваемые вопросы на собеседовании по C#

24. Чем задачи в C# отличаются от традиционных потоков? Объясните преимущества и сценарии, в которых задачи предпочтительнее прямого создания потоков.

И задачи (Task), и потоки (Thread) используются в C# для асинхронного и параллельного программирования. Однако между ними есть некоторые ключевые различия:
1) Уровень абстракции.
Задачи представляют собой абстракцию более высокого уровня, построенную на основе потоков и фокусирующуюся на выполняемой работе, а не на низкоуровневом управлении потоками. Потоки — это концепция более низкого уровня, позволяющая более детально контролировать детали выполнения.

2) Управление ресурсами.
Задачи используют пул потоков .NET для более эффективного управления рабочими потоками, сокращая накладные расходы на создание и уничтожение потоков. Потоки, создаваемые индивидуально для каждого действия, требуют больше ресурсов и плохо масштабируются для больших рабочих нагрузок.

3) Время жизни.
Потоки задач — это фоновые потоки, время жизни которых управляется системой. Thread может быть как фоновым, так и иметь приоритет, а время его существования контролируется разработчиком.

4) Асинхронное программирование.
Задачи интегрируются с шаблоном async/await для упрощения асинхронного программирования. Потоки требуют ручной синхронизации при координации с асинхронными операциями.

5) Продолжения.
Задачи позволяют упростить цепочку работ с помощью ContinueWith(), позволяя планировать выполнение работы после завершения предыдущей задачи. Для таких сценариев потоки требуют ручной синхронизации с использованием примитивов синхронизации.

6) Отмена.
Задачи предоставляют встроенный механизм отмены с использованием CancellationToken, предлагающий стандартизированный способ отмены и распространения запросов на отмену. Потоки должны реализовывать собственную логику отмены с использованием общих флагов или других механизмов синхронизации.

7) Обработка исключений.
Задачи лучше обеспечивают обработку исключений, объединяя исключения из нескольких задач и распространяя их в вызывающий контекст. Для потоков требуются более сложные механизмы обработки исключений, возникающих в дочерних потоках.

Когда использовать задачи:
- При работе с асинхронными или параллельными рабочими нагрузками. Можно извлечь выгоду из улучшенного управления ресурсами и масштабируемости ThreadPool.
- При использовании шаблона async/await для асинхронного программирования.
- Необходима координация работы с использованием продолжений.
- Необходим встроенный механизм отмены и стандартизированная обработка исключений.

Когда использовать потоки:
Вам нужен детальный контроль над выполнением, или у вас особые требования, которые не могут быть удовлетворены с помощью абстракций более высокого уровня (Task):
- Долгоживущие единицы работы: фоновые сервисы или сложные расчеты, требующие большего контроля над выполнением работ.
- Детальный контроль над выполнением потоков: установка приоритета или тонкая настройка синхронизации и прерываний.
- Низкоуровневое программирование.
- Взаимодействие с неуправляемым кодом.

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

Источник: https://dev.to/bytehide/c-multithreading-interview-questions-and-answers-4opj
👍31
День 1719. #ВопросыНаСобеседовании #Многопоточность
Самые часто задаваемые вопросы на собеседовании по C#

25. Как реализовать синхронизацию потоков с помощью ReaderWriterLockSlim? В чём его преимущества перед традиционным ReaderWriterLock?

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

Чтобы добиться синхронизации потоков с помощью ReaderWriterLockSlim, нужно:
1) Создать экземпляр ReaderWriterLockSlim.
2) Использовать EnterReadLock() перед доступом к общему ресурсу для чтения и ExitReadLock() после завершения операции чтения.
3) Использовать EnterWriteLock() перед доступом к общему ресурсу для записи и ExitWriteLock() после завершения операции записи.

var rwl = new ReaderWriterLockSlim();

// чтение
rwl.EnterReadLock();
try
{
// Доступ к общему ресурсу для чтения
}
finally
{
rwl.ExitReadLock();
}

// Запись
rwl.EnterWriteLock();
try
{
// Доступ к общему ресурсу для записи
}
finally
{
rwl.ExitWriteLock();
}

Преимущества ReaderWriterLockSlim над ReaderWriterLock:
1) Производительность: ReaderWriterLockSlim использует относительно дешёвую спин-блокировку и другие оптимизации для сценариев, в которых ожидается, что блокировка будет беспрепятственной или будет удерживаться в течение короткого времени.
2) Рекурсия: ReaderWriterLockSlim обеспечивает гибкую поддержку рекурсии блокировки, позволяя вам несколько раз входить и выходить из блокировки в одном потоке, тогда как ReaderWriterLock имеет ограничения на рекурсию.
3) Предотвращение нехватки писателей (writer starvation): ReaderWriterLockSlim имеет возможности уменьшить нехватку писателей, отдавая предпочтение запросам на блокировку записи вместо запросов на чтение. ReaderWriterLock может страдать от нехватки писателей при наличии непрерывного потока читателей.

Однако обратите внимание, что ReaderWriterLockSlim не поддерживает межпроцессную синхронизацию, и его не следует использовать, если объект блокировки необходимо использовать в нескольких процессах. В таких случаях используйте примитив синхронизации Mutex.

Источник: https://dev.to/bytehide/c-multithreading-interview-questions-and-answers-4opj
👍10
День 1743. #ВопросыНаСобеседовании #Многопоточность
Самые часто задаваемые вопросы на собеседовании по C#

26. Объясните концепцию ThreadLocal и секционирования данных, и как это может помочь улучшить общую производительность многопоточного приложения?

ThreadLocal
Локальное хранилище потока — это концепция, которая позволяет каждому потоку в многопоточном приложении иметь собственный экземпляр переменной. Локальная переменная потока сохраняет своё значение на протяжении всего времени существования потока и инициализируется один раз для каждого потока. Предоставляя каждому потоку свою копию переменной, мы можем минимизировать конфликты и повысить производительность, поскольку при доступе к переменной синхронизация не требуется.

В C# можно использовать класс ThreadLocal<T> для объявления локальной переменной потока:

var localSum = new ThreadLocal<int>(() => 0);

// Каждый поток может безопасно использовать и изменять свою localSum без синхронизации
localSum.Value += 1;

Свойство IsValueCreated локальной переменной потока возвращает true, если переменная уже была инициализирована в этом потоке. Так можно определить, что управление вернулось в созданный ранее поток.

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

Перераспределение может выполняться статически или динамически, в зависимости от конкретной задачи и целей приложения. Parallel.ForEach и Parallel LINQ (PLINQ) — это два примера встроенных механизмов .NET, которые используют секционирование данных для более эффективного выполнения параллельных операций.

Пример разделения данных с использованием Parallel.ForEach:

var data = new List<int> { … };
Parallel.ForEach(data, item =>
{
// обработка элемента
});

Итого
Локальное хранилище потоков и секционирование данных — это два способа значительно повысить производительность и эффективность многопоточных приложений на C#. Они помогают минимизировать конфликты, уменьшить накладные расходы на блокировку и лучше использовать доступные системные ресурсы. Очень важно выбрать подходящий метод, исходя из характера проблемы и задействованных алгоритмов.

Источник: https://dev.to/bytehide/c-multithreading-interview-questions-and-answers-4opj
👍21
День 1765. #ВопросыНаСобеседовании #Многопоточность
Самые часто задаваемые вопросы на собеседовании по C#


27. Опишите концепцию конфликта блокировок в многопоточности и объясните его влияние на производительность приложения. Как можно решить и смягчить проблемы, связанные с конфликтами блокировок?

Конфликт блокировок — это состояние, когда один поток ожидает другого, пытаясь получить блокировку. Какое бы время ни было потрачено на ожидание блокировки, это «потерянное» время, потраченное впустую. Очевидно, что это может вызвать серьезные проблемы с производительностью. Конфликты блокировок могут быть вызваны любым типом механизма синхронизации потоков. Это может быть из-за оператора блокировки, AutoResetEvent/ManualResetEvent, ReaderWriterLockSlim, Mutex или Semaphore и всех остальных. Всё, что заставляет один поток приостанавливать выполнение до тех пор, пока не поступит сигнал другого потока, может вызвать конфликт блокировок.

Влияние конфликта блокировок:
- Увеличение времени ожидания
Потоки, ожидающие снятия блокировки, испытывают увеличенную задержку, что снижает общую пропускную способность приложения.
- Снижение параллелизма
Когда несколько потоков ожидают блокировки, вероятность параллелизма снижается, что делает приложение менее эффективным в использовании аппаратных и системных ресурсов.
- Риск взаимоблокировок
Высокая конкуренция за блокировки может увеличить риск взаимоблокировок, когда два или более потоков ждут блокировок, удерживаемых друг другом.

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

2. Сократите продолжительность блокировки
Минимизируйте время, проводимое внутри заблокированной области, выполняя только важные операции и перемещая некритические задачи за пределы заблокированной области.

3. Используйте структуры данных и алгоритмы без блокировки
Если возможно, используйте неблокирующие алгоритмы и структуры данных, которые не полагаются на блокировки, такие как ConcurrentQueue, ConcurrentDictionary или ConcurrentBag.

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

5. Минимизируйте конфликты с помощью секционирования
Разделите данные на секции, обрабатываемые отдельными потоками, что снизит необходимость синхронизации.

6. Избегайте вложенных блокировок
Уменьшите риск взаимоблокировок и конфликтов, избегая вложенных блокировок или иерархий блокировок.

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

Источник: https://dev.to/bytehide/c-multithreading-interview-questions-and-answers-4opj
👍24
День 1841. #ВопросыНаСобеседовании #ASPNET
Самые часто задаваемые вопросы на собеседовании по C#

28. Как сервер Kestrel работает в среде .NET Core и чем он отличается от других веб-серверов?

Kestrel — кроссплатформенный веб-сервер, созданный для приложений на базе .NET Core. Его также можно использовать в сочетании с обратным прокси-сервером, таким как Apache, Nginx или IIS, который обеспечивает дополнительный уровень конфигурации, безопасности и балансировки нагрузки.

Ключевые особенности:
- Кроссплатформенность.
- Высокая производительность: оптимизирован для эффективной обработки большого количества одновременных подключений.
- Легковесность: оптимизирован для работы в средах с ограниченными ресурсами, таких как контейнеры.
- Повышенная безопасность: поддерживает HTTPS и защищён от уязвимостей веб-сервера.
- Широкая поддержка протоколов: HTTP/1.1, HTTP/2 и HTTP/3, WebSocket.
- Бесшовная интеграция с компонентами ASP.NET Core, такими как конвейер промежуточного ПО, внедрение зависимостей и система конфигурации.
- Множество рабочих нагрузок: ASP.NET (минимальные API, MVC, страницы Razor, SignalR, Blazor и gRPC), а также обратные прокси с помощью YARP.
- Расширяемость: возможность настройки с помощью конфигурации, промежуточного ПО и т.п.
- Встроенные функции диагностики производительности, такие как ведение журнала и метрики.

Место, которое Kestrel занимает в процессе обработки запроса показано на рисунке ниже. Обратный прокси (Apache, Nginx или IIS) пересылает запрос в веб-сервер ASP.NET Core (по умолчанию Kestrel). Kestrel принимает низкоуровневый сетевой запрос и использует его для создания объекта HttpContext, который может использовать остальная часть приложения. Веб-сервер заполняет HttpContext подробностями исходного HTTP-запроса и другими деталями конфигурации и передаёт их остальной части приложения.

Kestrel отвечает за получение данных запроса и создание представления запроса на C#, но не пытается обрабатывать запрос напрямую. Для этого он передаёт HttpContext в конвейер промежуточного ПО, где выполняются стандартные для всех запросов операции вроде журналирования, обработки исключений или обслуживания статических файлов.

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

Источники:
-
https://dev.to/bytehide/net-core-interview-question-answers-4bc1
- Эндрю Лок “
ASP.NET Core в действии”. 2-е изд. – М.: ДМК Пресс, 2021. Глава 2.
👍11👎1
День 1861. #ВопросыНаСобеседовании #Многопоточность
Самые часто задаваемые вопросы на собеседовании по C#

29. Какие потенциальные проблемы могут возникнуть при использовании Thread.Abort() для завершения работающего потока? Объясните последствия и предложите альтернативные методы корректной остановки потока.

Использование Thread.Abort() для завершения работающего потока может привести к нескольким потенциальным проблемам:
1. Непредсказуемое состояние.
Thread.Abort() вызывает исключение ThreadAbortException, которое немедленно прерывает поток, потенциально оставляя общие ресурсы, структуры данных или критические разделы в несогласованном состоянии.
2. Утечки ресурсов.
Если прерванный поток выделил ресурсы, такие как дескрипторы, файловые потоки или соединения с базой данных, они могут не быть освобождены, что приведёт к утечке ресурсов.
3. Взаимные блокировки.
Прерванные потоки, удерживающие блокировки или другие примитивы синхронизации, могут не иметь возможности их освободить, что приводит к взаимоблокировкам в других потоках.
4. Обработка ThreadAbortException.
Если поток перехватывает ThreadAbortException и игнорирует его, запрос на прерывание завершится неудачно, и поток продолжит выполнение.
5. Устарело и больше не поддерживается.
Метод Thread.Abort() не поддерживается в .NET Core, .NET 5 и более поздних версиях, что указывает на то, что его не следует использовать в современных приложениях.

Чтобы корректно остановить поток, есть следующие альтернативы.

1. Общий флаг
Добавим логический флаг, который будет периодически проверяться выполняемым потоком. Если флаг установлен в true, поток должен завершиться. Обязательно использовать ключевое слово volatile или класс Interlocked, чтобы обеспечить правильную синхронизацию:
volatile bool stopRequested = false;
var thread = new Thread(() => {
while (!stopRequested)
{
// выполняем работу
// ...
}
});

// Останавливаем поток
stopRequested = true;


2. Токен отмены
Если использовать задачи вместо потоков, библиотека параллельных задач (TPL) предоставляет модель отмены с использованием токена отмены:
var cts = new CancellationTokenSource();
var task = Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
// Выполняем работу
// ...
}
});

// Останавливаем задачу
cts.Cancel();

Грамотная остановка потоков с помощью этих методов гарантирует освобождение ресурсов, правильное управление блокировками и сохранение согласованного состояния общих данных. Она также совместима с современными версиями .NET и TPL.

Источник: https://dev.to/bytehide/c-multithreading-interview-questions-and-answers-4opj
👍22
День 1871. #ВопросыНаСобеседовании #ASPNET
Самые часто задаваемые вопросы на собеседовании по C#


30. Какие существуют возможности управления конфигурацией приложения .NET Core в разных средах (разработка/тестирование/производство)?

.NET Core предоставляет решение для управления конфигурациями в различных средах с помощью поставщиков конфигурации.

Во-первых, задать среду. Приложения .NET Core делают это, читая переменную окружения ASPNETCORE_ENVIRONMENT. Значение по умолчанию – "Production". Формально значение может быть любым, но лучше придерживаться одного из трёх стандартных:
- Development
- Staging
- Production
Это даст доступ, например, к методам расширения, таким как IHostingEnvironment.IsDevelopment(). Значение можно задать в переменных окружения машины. IDE, такие как Visual Studio, также могут брать это значение из файла launch.json из корня проекта.
Кроме того, среду можно задать принудительно в коде, вручную настроив веб хост:
var builder = new WebHostBuilder()
.UseEnvironment(Environments.Production)
.UseKestrel()
.… ;

Среда определяется на раннем этапе старта приложения, поэтому дальнейшую настройку можно определять в зависимости от среды. Например, для управления конфигурацией можно использовать файл appsettings.json, который является файлом по умолчанию, считываемым приложением .NET Core. Можно иметь отдельные файлы конфигурации для каждой среды, например appsettings.Development.json или appsettings.Production.json, что даёт возможность переопределить настройки по умолчанию.

Вообще есть несколько вариантов настройки:
1. Использовать различные настройки в коде в зависимости от среды, например:

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

2. Использовать различные файлы appsettings.{Environment}.json для хранения конфигураций, специфичных для среды.

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

4. Важно исключить конфиденциальные данные, такие как строки подключения и секреты приложений, из системы управления версиями (например, файлов appsettings.json). Их лучше хранить либо в переменных среды, либо использовать безопасные методы, такие как пользовательские секреты в среде разработки или сервисы вроде Azure Key Vault в производственной среде.

В приложении использовать интерфейс IConfiguration для доступа к настроенным параметрам. См. подробнее.

См. также про изменения в конфигурации введённые в .NET6.

Источники:
-
https://dev.to/bytehide/net-core-interview-question-answers-4bc1
- Эндрю Лок “
ASP.NET Core в действии”. 2-е изд. – М.: ДМК Пресс, 2021. Глава 11.
👍23
День 1910. #ВопросыНаСобеседовании #ASP.NET #Architecture
Самые часто задаваемые вопросы на собеседовании по C#

31. Как бы вы подошли к обработке ошибок и отладке в распределённом приложении .NET Core с несколькими микросервисами?

Обработка ошибок и отладка в таком приложении может оказаться сложной задачей. Можно использовать несколько стратегий:

1. Централизованные логи.
Все микросервисы должны отправлять свои логи (естественно, структурированные) в централизованное место, где они сопоставляются и индексируются. Это позволит искать и визуализировать логи всех сервисов в одном месте.

2. Использование идентификаторов корреляции.
Идентификаторы корреляции (CorrelationId) — это уникальные идентификаторы, присваиваемые запросу. Затем этот идентификатор передаётся всем сервисам, участвующим в обработке этого запроса. Это позволяет отслеживать всю цепочку запросов и ответов.

3. Проверки работоспособности.
Проверки работоспособности можно реализовать для мониторинга состояния микросервисов. Они могут сообщать такие показатели, как время безотказной работы, загрузка ЦП, использование памяти и т. д.

4. Промежуточное ПО для обработки исключений.
В архитектуре микросервисов ошибки должны обрабатываться на уровне сервиса. Каждый сервис должен обрабатывать свои собственные исключения и возвращать подходящее сообщение об ошибке или код ответа.
Можно создать промежуточное ПО, которое обрабатывает каждый запрос микросервиса. Если во время выполнения запроса возникает исключение, это промежуточное ПО перехватит исключение и ответит подходящим сообщением об ошибке.
См. также «Улучшенная Обработка Исключений в ASP.NET Core 8.»

5. Использовать распределённую систему трассировки.
Она собирает данные и показатели от каждого микросервиса, а затем сопоставляет эти данные в комплексный визуальный обзор производительности системы. См. документацию.

Источник: https://dev.to/bytehide/net-core-interview-question-answers-4bc1
👍21
День 2445. #ВопросыНаСобеседовании
Давно не было на канале вопросов с собеседований. Смотрите все посты на эту тему по хэштэгу выше. Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы). Я решил разобрать их тут. Начнём с 4го, поскольку первые 3 приведены в его книге, обзор на которую я недавно выкладывал.

4. Интерфейсы и абстрактные классы
«Когда в .NET следует использовать интерфейс, а когда — абстрактный класс? Приведите примеры ситуаций, в которых один вариант будет более подходящим, чем другой».

Хороший ответ
«В .NET и интерфейсы, и абстрактные классы используются для определения контрактов в коде, но их применение различается в зависимости от необходимости наследования и типа полиморфизма.

Интерфейсы лучше всего использовать, когда нужно определить контракт для того, что делает класс, не навязывая ему, как именно это должно быть реализовано. Интерфейсы идеально подходят, когда требуется, чтобы несколько несвязанных классов реализовали один и тот же набор методов, гарантируя, что все реализующие классы будут придерживаться определённого поведения. Например, можно использовать интерфейс для определения стандартной структуры для различных типов платежей, где каждый тип платежа, такой как CreditCard, PayPal, Bitcoin, реализует методы обработки платежей, определённые интерфейсом.

Абстрактные классы используются, когда требуется общий код для нескольких тесно связанных классов. Абстрактный класс может предоставлять определённое поведение по умолчанию, а также определять абстрактное поведение, которое должно быть реализовано подклассами. Например, если вы создаёте приложение, моделирующее геометрические фигуры, можно использовать абстрактный класс для определения методов по умолчанию для вычисления площади и периметра, требуя при этом, чтобы подклассы, такие как Circle, Rectangle и Triangle, реализовали свои специфические вычисления.

Выбор между использованием интерфейса и абстрактного класса часто сводится к тому, нужно ли вам совместно использовать код (использовать абстрактный класс) или просто обеспечить общий интерфейс, не заботясь об иерархии (использовать интерфейс)».


Часто встречающийся неудачный ответ
«Я использую абстрактный класс всякий раз, когда мне нужно определить методы, которые не следует изменять, а интерфейсы — когда мне нужно просто реализовать множество различных методов. Поэтому, если у меня есть методы, которые не следует переопределять, я помещаю их в абстрактный класс».


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

- Непонимание абстрактных классов: Абстрактные классы предназначены не только для определения методов, которые «не следует изменять». Хотя абстрактный класс действительно может содержать конкретные методы, их основное предназначение — служить базовым классом для расширения другими классами, предоставляя общий код и определяя абстрактные методы, которые должны быть реализованы подклассами. Тот факт, что они могут включать непереопределяемые методы (с помощью ключевого слова sealed в C#), является второстепенным по сравнению с их основной функцией.

- Непонимание интерфейсов: Утверждение, что интерфейсы используются «только для реализации набора различных методов», слишком упрощает их роль. Интерфейсы определяют контракт, которому следуют классы, что критически важно для разработки систем, в которых различные классы могут использоваться взаимозаменяемо, не зная их конкретных реализаций.

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

Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍21👎2
День 2452. #ВопросыНаСобеседовании
Марк Прайс в своей книге предложил свой набор из 60 вопросов на собеседовании.

5. Свойства и индексаторы

«Можете ли вы объяснить разницу между свойствами и индексаторами в C# и привести примеры ситуаций, в которых каждый из них может быть использован?»

Хороший ответ
«В C# свойства и индексаторы используются для инкапсуляции данных, но они служат разным целям и используются в разных контекстах. Свойства действуют как комбинация метода и поля, предоставляя способ получения и установки значений с дополнительной логикой, используя синтаксис, подобный синтаксису полей. Свойства наиболее подходят, когда требуется предоставить данные класса с потенциальной проверкой, вычислением или преобразованием. Например, класс Person может иметь свойство DateOfBirth, которое гарантирует, что дата установлена в прошлом, и вычисляет возраст человека при получении.

Индексаторы позволяют индексировать объект как массив, хотя ключ может быть любого типа данных, а не только целочисленным. Это особый тип свойства, позволяющий получать доступ к классам с помощью оператора доступа к массиву []. Индексаторы особенно полезны, когда класс представляет собой коллекцию элементов. Например, класс Library может использовать индексатор, чтобы предоставить клиентам доступ к книгам по числовому индексу.

Как свойства, так и индексаторы включают методы доступа get и set (или только один из них), и оба могут включать в себя дополнительную логику в этих методах для обеспечения инкапсуляции или управления побочными эффектами.»


Часто встречающийся неточный ответ:
«Я использую свойства, когда мне нужно хранить данные в полях, и индексаторы, когда я хочу использовать массивы в своих классах».

Этот ответ отражает непонимание как свойств, так и индексаторов:

- Непонимание свойств: Свойства предназначены не только для хранения данных; они используются для инкапсуляции доступа к данным и могут включать логику проверки, значения по умолчанию или другие преобразования. Это не просто поля, а более сложные функции.

- Непонимание индексаторов: Индексаторы — это не просто способ реализации массивов внутри классов. Они позволяют индексировать экземпляр класса подобно массивам, но и служат для того, чтобы класс вёл себя как коллекция. Это непонимание принижает роль индексаторов в абстракции и инкапсуляции.

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

Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍11
День 2459. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы). Я решил разобрать их тут. Начнём с 4го, поскольку первые 3 приведены в его книге, обзор на которую я недавно выкладывал.

6. Обобщения (дженерики)

«Можете объяснить преимущества использования обобщений в приложениях .NET и привести пример сценария, в котором использование обобщений может значительно улучшить качество и производительность кода?»

Хороший ответ
«Обобщения в .NET предоставляют возможность записывать определения классов, методов, делегатов или интерфейсов с параметром для типа, с которым они работают. Это обеспечивает повторное использование кода и типобезопасность без накладных расходов на упаковку или приведение типов, что часто встречается в необобщенных типах.

Основные преимущества использования обобщений включают в себя:
- Безопасность типов: обобщения позволяют указывать точный тип при создании экземпляра класса или метода, что снижает количество ошибок во время выполнения.
- Повторное использование кода: благодаря использованию параметров типа, обобщённые классы и методы могут работать с любым заданным типом, что позволяет разработчикам писать более гибкий и повторно используемый код.
- Повышение производительности: обобщения устраняют необходимость в упаковке и распаковке при работе с типами значений, что снижает потребление памяти и повышает производительность.

Пример сценария, в котором обобщения значительно повышают качество и производительность кода, — реализация классов-коллекций. Например, без обобщений список из целых чисел, хранил бы их как объекты (тип object), что потребовало бы упаковки. С обобщениями можно создать List<int>, в котором целые числа хранятся как целые числа, а не объекты, что устраняет необходимость в упаковке и распаковке, повышает производительность выполнения и снижает накладные расходы на память.

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


Часто встречающийся неверный ответ
«Я использую обобщения, когда мне нужно обрабатывать разные типы данных одним и тем же методом или когда я хочу, чтобы мой метод был гибким. Это всё равно, что заставить метод работать с любым типом данных».

Этот ответ демонстрирует понимание обобщений на элементарном уровне, но упускает важные детали и преимущества:

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

- Чрезмерное упрощение: Концепция обобщений сводится просто к «работе с любым типом», что упускает из виду истинное их предназначение — обеспечение повторного использования кода и безопасности в типоспецифичных операциях.

- Непонимание реализации: В этом ответе не проводится различие между использованием обобщений для обеспечения типобезопасности и необобщённым подходом с использованием типов object, что может привести к проблемам с производительностью и не обеспечивает проверку типов во время компиляции, которую обеспечивают обобщения.

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

См. также Ковариантность и Контравариантность в Обобщениях.

Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍7