Вопросы на собеседовании по C#
Самые популярные и задаваемые вопросы на собеседованиях .Net разработчика.
Так же смотрите статью Вопросы на собеседовании для Senior .NET Developer
Общие вопросы
В чем разница между интерфейсно-ориентированным, объектно-ориентированным и аспектно-ориентированным программированием?
Аспектно-ориентированное
Аспектно-ориентированное програмирование базируется на изучении того сколько и каких компонент или частей требуется для взаимодействия с системой. Основным для АОП является взаимодействие этих элементов.
Интерфейсно-ориентированное
Интерфейсно-ориентированное программирование это подход основанный на программировании по контракту. Ни одна часть интерфейса не зависит от того как реализована другая, вся коммуникация между ними описана в контракте. Веб-сервисы на основе WSDL наиболее известный пример этого подхода.
Объектно-ориентированное
Объектно-ориентированное программирование основывается на понятиях абстракции, инкапсуляции, полиморфизма и наследования. Классы реализуют эти концепции для построение объектов, контролирующих или реализующих систему.
Абстракция позволяет уменьшить связывание между компонентами пердоставляя дополнительный слой между ними, для того чтоб один объект не зависил от того, как другой реализуюет свои бизнес-правила. (Интерфейсы, слои) Отличная штука, если вы хотите изолировать части системы так, чтоб их изменение или замена не стали проблеммой для работы системы в целом.
Инкапсуляция позволяет работать абстракции пряча детали реализации класса от вызывающих его. (Публичные и приватные поля)
Наследование позволяет базовым(родительским) классам содержать общую функциональность и передавать ее всем своим классам-потомкам. Класс Figure(фигура) может иметь поле цвет, которое будет унаследовано его классами-потомками Square(квадрат) или Circle(круг).
Полиморфизм позволяет реализовывать одноименные публичные методы, позволяя различным классам выполнять различные действия при одном и том же вызове. То есть объекты классов Square и Circle могут отображаться(реализовывать метод render) поразному несмотря не то, что они оба подклассы Shape, метод render определен в Shape. (Overriding)
Что такое CLR? Что такое IL? Что такое CLS?
CLR ("Common Language Runtime", "общеязыковая исполняющая среда") - это компонент .NET Framework, основной задачей которого является управление интерпретацией и исполнением кода IL. CLR отвечает за изоляцию памяти приложений, проверку типов, безопасность кода, преобразование IL в машинный код.
IL (Intermediate Language) - код, содержащий набор инструкций, не зависящих от платформы. Иными словами, после компиляции исходного кода он преобразуется не в код для какой-то определенной платформы, а в промежуточный код на языке IL.
CLS ("Common Language Specification", общеязыковая спецификация) - это набор правил, следуя которым разработчики достигают бесконфликтной работы во всех языках .NET.
Что такое managed code?
Управляемый код (managed code) - это код, работающий в среде CLR. Содержит метаданные, в которых находится информация для среды выполнения - о типах, членах и ссылках, используемых в коде.
Что такое assembly?
Сборка (assembly) - один или несколько файлов, содержащий логический набор функциональности (код и другие данные, связанные с кодом). Бывают статические сборки, хранящиеся на диске, и динамические, которые создаются во время выполнения программы. Сборка - это базовый блок приложения, все ресурсы, относящиеся к ней, доступны или только внутри этого блока, или экспортируются наружу. При выполнении сборка задает область видимости имен и следит за ее соблюдением.
Что такое приватные и совместные сборки?
Сборки (assembly) бывают двух типов - приватные (private), которые использует только само приложение, и совместные (shared), использующиеся набором приложений. При приватных сборках приложение изолируется от внешнего воздействия программ и операционной системы, отпадает необходимость заботиться об уникальности имен в глобальном пространстве имен. Чтобы сделать сборку совместной, ее необходимо специальным образом собрать и присвоить ей строгое шифрованное имя.
Что такое assembly manifest?
Манифест сборки (assembly manifest) - это внутренняя часть сборки, которая позволяет ей быть самоописанной. Assembly manifest позволяет идентифицировать сборку, указывает файлы, которые включаются в реализацию сборки, описывает типы и ресурсы, используемые в сборке, указывает зависимости от других сборок, а также набор прав доступа, которые необходимы сборке для корректной работы. Эта информация используется во время выполнения для разрешения ссылок, проверку корректности версий, проверку целостности загруженных сборок.
В чем разница между понятиями namespace и assembly?
Namespace (пространство имен) является логическим соглашением, используемым во время разработки, в то время как assembly (сборка) устанавливает область видимости имени в процессе выполнения.
В чем различие между Value Type и Reference Type?
Value Type находятся в стеке, а Reference Type в куче.
Когда объект удаляется сборщиком мусора?
Объект удаляется сборщиком мусора, когда на него не остается ссылок.
Что такое Code Access Security (CAS)?
CAS - это защитная технология, позволяющая установить ограничение на исполнение управляемого кода. Таким образом можно определить разрешения и установить права доступа к ресурсам компьютера.
Что такое attribute?
Атрибут (attribute) - это универсальное средство связи данных с типами, позволяют добавлять любую текстовую информацию о классах, свойствах, методах и т.д. Атрибуты сохраняются с метаданными и могут быть получены при выполнении программы.
Как обеспечить использование именованных параметров в конструкторе атрибута?
Конструкторы атрибутов могут принимать именованные параметры — поля и свойства атрибутов. При задании именованного параметра в конструктор атрибута передается имя свойства или поля, которое должно принять этот параметр. При чем эти свойства и поля должны быть открытыми. Если именованные параметры передаются, то они обязательно должны идти следом за позиционными параметрами, которые явно указаны в конструкторе атрибута. Указание именованных параметров не является обязательным, поэтому при проектировании атрибутов необходимо помнить о том, что некоторые его поля или свойства могут быть не проинициализированы. Пример использования именованных параметров в конструкторе атрибута:
[DllImport("Kernel32", CharSet=CharSet.Auto, SetLastError=true)]
Здесь передается 1 позиционный параметр — строка "Kernel32" и 2 именованных параметра, которые устанавливают открытые поля CharSet и SetLastError в значения CharSet.Auto и true соответственно.
В чем различие между Finalize и Dispose?
Dispose - обеспечивает явный контроль над ресурсами, используемыми объектом, а Finalize - неявный, используемый сборщиком мусора.
Что такое Boxing и Unboxing?
Упаковка (boxing) позволяет преобразовать размерный тип в ссылочный. При упаковке объекта размерного типа происходят следующие действия:
- Выделяется память в управляемой куче.
- Совершается копирование полей размерного типа в память, которая была выделена в куче.
- Возвращается адрес объекта.
Некоторые компиляторы автоматически создают IL-код, необходимый для упаковки объекта размерного типа. Процесс извлечения адреса полей из упакованного объекта называется распаковкой (unboxing). Распаковка не является полной противоположностью упаковке. В отличие от упаковки при распаковке не происходит никакого копирования. Однако обычно вслед за распаковкой следует копирование полей, поэтому обе операции (распаковка и копирование) являются противоположностью операции упаковки. Приведем пример использования упаковки и распаковки.
struct Point { public Int32 x, у; } class App { static void Main() { ArrayList a = new ArrayList(); Point p; // Выделяется память для Point (не в куче). for (Int32 i = 0 ; i < 10; i++) { p.x = p. у = i; // Инициализация членов в нашем размерном типе. a.Add(p); // Упаковка размерного типа и добавление ссылки в ArrayList. } Point р1 = (Point) a[0]; // распаковка и копирование полей }
Упаковка и распаковка/копирование снижают производительность приложения как в плане замедления, так и в расходе дополнительной памяти, поэтому нужно стараться минимизировать создание кода, в котором происходят операции упаковки и распаковки/копирования.
Что такое GAC?
GAC — это глобальный кэш сборок. В нем хранятся совместно используемые сборки. Обычно это каталог С:\Windows\Assembly\GAC. Этот каталог имеет определенную структуру, в котором хранятся подкаталоги, имена которых сгенерированы по определенному алгоритму. В GAC можно поместить только сборки со строгими именами. Для того, чтобы поместить сборку в GAC, используют специальный инструмент GACUtil.exe, который знает всю внутреннюю структуру GAC и может генерировать имена подкаталогов надлежащим образом. Регистрировать в GAC сборки необходимо для того, чтобы избежать конфликтов имен сборок. Приведем пример: две компании выпустили сборку и назвали ее одним именем Calculus. Если мы скопируем эту сборку в каталог, в котором уже находится сборка с таким же именем, то мы затрем сборку, которая ранее могла использоваться каким-то приложением. Это приложение с новой сборкой теперь работать не сможет. Решением этой проблемы будет регистрация этих двух сборок в GAC, в котором для каждой будет создан отдельный каталог.
Какие типы можно использовать в предложении foreach?
Массивы, коллекции. Классы в которых реализован интерфейс System.Collections.IEnumerable.
В чем различие между классом и структурой?
Для С# классы System.Object, System.Exception, System.File-Stream и System.Random — это ссылочные типы (память выделяется из упр. кучи). В свою очередь размерные типы в документации называются структурами (structure) и перечислениями (enumeration). Например, структуры System.In132, System.Boolean, System.Decimal, System.TimeSpan и перечисления System.DayOfWeek, System.10.FileAttributes и System.Drawing.FontStyle являются размерными типами (хранятся обычно в стеке потока, но могут быть встроены в ссылочные типы).
Что означает модификатор virtual?
При наследовании класса. Данный метод м.б. переопределен в производных классах с помощью ключевого слова override.
Чем отличается event от delegate?
Delegate – это по сути указатель на функцию.
В С# модель издатель — подписчик, где класс публикует событие, которое он может инициировать, и любые классы могут подписаться на это событие. Метод, вызываемый при возникновении события, определяется делегатом
Может ли класс реализовать два интерфейса, у которых объявлены одинаковые методы? Каким образом?
Да.
public class GiuseppePizzaria : IWindow, IRestaurant { // Реализация метода GetMenu интерфейса IWindow. Object IWindow.GetMenu() { ... } // Реализация метода GetMenu интерфейса IRestaurant. Object IRestaurant.GetMenu() { ... } }
Поддерживает ли C# множественное наследование?
С# поддерживает множественное наследование в виде наследования от класса и нескольких интерфейсов, или просто от нескольких интерфейсов.
Но не поддерживает наследование от нескольких классов.
Кому доступны переменные с модификатором protected на уровне класса?
Любому классу-наследнику
Наследуются ли переменные с модификатором private?
Да, но они не являются доступными.
Опишите модификатор “protected internal”
Члены с таким модификатором доступны классам, находящимся в той же сборке и унаследованным от данного класса.
Назовите класс .NET, от которого наследуются все классы?
System.Object.
Что обозначает термин immutable (неизменяемый)?
Это значит, что данные, хранящиеся в переменной, не могут быть изменены. При этом заметьте, что значение переменной может быть изменено - путём отказа от использования старых данных, которые могут быть изменены. Оригинальные данные остаются в памяти, а новые значения создаются вновь, в новой области памяти. Пример тип String.
Какая разница между классами System.String и System.Text.StringBuilder?
Данные, хранящиеся в классе System.String и есть неизменяемые (immutable). Класс System.StringBuilder разрабатывался так, чтобы над изменяемой строкой можно было проделать множество операций. То есть при каждой операции над объектом класса System.String происходит перенос данных в новую область памяти, что влияет на производительность программы.
Какое преимущество использования класса System.Text.StringBuilder перед System.String?
Класс StringBuilder более эффективен в случае работы с большим количеством строк. Объекты класса System.String неизменяемы, поэтому при каждом изменении строки создаётся новый объект в памяти.
Можно ли хранить разные типы данных в объекте класса System.Array?
Да
static void Main(string[] args) { object[] arr = new object[] { "string", 0, new Guid() }; foreach (object var in arr) { Console.WriteLine(var.GetType().ToString()); } Console.ReadKey(); double d = 0.0; ValueType[] arr2 = new ValueType[] { d, 0, new Guid() }; foreach (ValueType var in arr2) { Console.WriteLine(var.GetType().ToString()); } Console.ReadKey(); }
Объясните разницу между System.Array.CopyTo() и System.Array.Clone()?
Первая операция осуществляет глубокое копирование массива, а вторая – поверхностное. Поверхностное копирование массива копирует только сами элементы объекта класса Array, независимо от того являются они ссылочными или значимыми типами. Копирования объектов, на которые ссылаются ссылочные типы не происходит. Ссылки в новом объекте класса Array указывают на те же объекты, что и ссылки в оригинальном массиве Array. Глубокое копирование копирует как элементы класса Array, так и объекты, на которые они явно или неявно ссылаются.
Как отсортировать элементы массива в убывающем порядке?
Нужно вызвать метод Sort(), а затем метод Reverse().
As, is – что это, как применяется?
С помощью оператора as программа пытается преобразовать выражение к определенному типу, при этом не выбрасывает исключение. В случае неудачного преобразования выражение будет содержать значение null.
Выражение o is Employee
проверяет, является ли переменная o объектом типа Employee.
Операторы приведения типов.
If(o is Employee){
Employee e = (Employee) o;
}
В чем разница между throw ex;
и throw;
?
throw
повторно выбрасывает исключение (re-throw), которое было обнаружено, и сохраняет трассировку стека (путь к источнику исключения).throw ex
генерирует одно и то же исключение, но сбрасывает трассировку стека на метод, где делается throw ex.
Как работает return в try-catch-finally?
Алгоритм приблизительно такой:
- Выполняется код перед оператором return;
- Выражение в return оценивается
- Выполняется finally блок
- Возвращается результат, посчитанный на шаге 2
Рассмотрим следующий код:
public static async Task Main()
{
Console.WriteLine(MyMethod().Text);
Console.ReadKey();
}
public static TestClass MyMethod()
{
var number = new TestClass
{
Text = "5"
};
try
{
return number;
}
catch
{
number.Text = "haha";
return number;
}
finally
{
number.Text = "finally";
}
}
Что мы получим на экране?
finally
почему так? Мы не меняли результат который был получен на шаге 2, мы изменили значение свойства ссылочного типа, но не меняли сам объект
Если мы перепишем блок finally следующим образом:
...
finally
{
number = new TestClass {Text = "finally"};
}
то получим в ответ
5
Если мы проделаем это с value type, результат будет тем же. Т.е в блоке finally нельзя изменить возвращаемый объект, но можно менять свойства объекта.
Вопросы по классам
Какой синтаксис используется для указания класса родителя в C#?
После имени класса наследника нужно поставить двоеточие и указать имя базового класса. Пример:
class ChildClass : ParentClass
Можно ли запретить наследование от своего собственного класса?
Да. Для этого служит ключевое слово “sealed”.
Можно ли разрешить наследование класса, но запретить перекрытие метода?
Да. Указываем класс как public, а метод как sealed.
Что такое абстрактный класс?
Это класс, объект которого не может быть создан. Такой класс должен иметь класс-наследник с реализацией абстрактных методов. Абстрактный класс – это фактически чертёж нормального класса без реализации.
В каком случае вы обязаны объявить класс абстрактным?
- В том случае, если класс является наследником абстрактного класса, но не все методы базового класса перекрыты и имеют реализацию.
- В том случае, если хотя бы один метод класса является абстрактным.
Что такое интерфейс класса?
Интерфейсы, как и классы, определяют набор свойств, методов и событий. Но, в отличие от классов, они не содержат их реализации. Интерфейсы реализуются классами и определяются как самостоятельные сущности.
Почему нельзя указать модификатор видимости для методов интерфейса?
Потому что все они должны иметь модификатор public, который и установлен по умолчанию.
Можно ли наследовать от нескольких интерфейсов?
Да.
Назовите отличия между интерфейсом и абстрактным классом?
В интерфейсе все методы (свойства и т.д.) абстрактны и не имеют реализации. В абстрактном классе некоторые методы могут быть реализованы. В интерфейсе члены не могут иметь модификатора видимости (все они являются public по умолчанию), а в абстрактном классе члены могут иметь модификатор видимости.
Назовите различия между структурами и классами.
Для С# классы System.Object, System.Exception, System.File-Stream и System.Random — это ссылочные типы (память выделяется из упр. кучи). В свою очередь размерные типы в документации называются структурами (structure) и перечислениями (enumeration). Например, структуры System.In132, System.Boolean, System.Decimal, System.TimeSpan и перечисления System.DayOfWeek, System.10.FileAttributes и System.Drawing.FontStyle являются размерными типами (хранятся обычно в стеке потока, но могут быть встроены в ссылочные типы).
В чем разница между абстрактными и виртуальными классами? Между виртуальными и абстрактными методами?
Абстрактный класс это класс, содержащий хотя бы один метод (abstract).. Виртуальный метод имеет реализацию и м.б. переопределен в производном классе. Абстрактный метод не имеет реализацию, только описание метода, который д.б. реализован в производных классах.
Dispose(), Finalize() – что это за методы, как используются в .NET?
Используются для освобождения ресурсов. Применяя метод Dispose, вы должны обеспечить неявную очистку методом Finalize. Если программисту не удалось вызвать метод Dispose, использование метода Finalize предотвращает постоянную утечку ресурсов.
Для чего в .NET используется конструкция using(…){…}? Причем тут IDisposable?
Значение Using непосредственно связано с интерфейсом IDisposable. Интерфейс IDisposable представляет нам возможность быстро освободить общие ресурсы, не полагаясь на автоматический сборщик мусора (garbage collector). Конструкция Using позволяет вызывать метод Dispose автоматически, как только нужный объект выйдет за блок Using.
Вопросы по методам и свойствам
Назовите явное имя параметра, передаваемого в метод set свойства класса?
value. Тип этого параметра определяется типом свойства.
Что обозначает ключевое слово “virtual” для метода или свойства?
То, что метод или свойство может быть перекрыто.
Чем перекрытый метод отличается от перегруженного метода?
При перекрывании метода мы изменяем его поведение в классе наследнике. Перегрузка метода просто приводит к использованию другого метода с тем же именем внутри класса.
Можно ли объявить перекрытый метод статическим, если перекрываемый метод не является статическим?
Нет. Сигнатура виртуального метода должна остаться постоянной, кроме замены ключевого слова virtual на ключевое слово override.
Вопросы по сборкам
Что такое «сопутствующая сборка» (satellite assembly)?
Сборки, помеченные определенными региональными стандартами, называются сателлитными сборками
Какая наименьшая исполнимая единица в .NET?
сборка
Что происходит в памяти при упаковке и распаковке значимого типа?
При упаковке экземпляра размерного типа происходит следующее.
- В управляемой куче выделяется память. Ее объем определяется длиной размерного типа и некоторыми накладными расходами, позволяющими этому размерному типу стать настоящим объектом. Этими накладными расходами являются указатель на таблицу методов и индекс SyncBlocklndex.
- Поля размерного типа копируются в память, выделенную только что в куче.
- Возвращается адрес объекта. Этот адрес является ссылкой на объект; размерный тип превратился в ссылочный.
Распаковка не является точной противоположностью упаковки.
Она состоит только в получении указателя на исходный.
размерный тип (поля данных), содержащийся в объекте. И никакого копирования при распаковке (в отличие от упаковки). Однако обычно вслед за распаковкой выполняется копирование полей, поэтому в сумме обе эти операции являются отражением операции упаковки