MyTetra Share
Делитесь знаниями!
Using + IDisposable
Время создания: 07.09.2020 05:34
Автор: Юрий Шпорхун Skillbox
Текстовые метки: skillbox, вопросы собеседований, Using, IDisposable
Раздел: Компьютер - C#
Запись: Kozlov-AE/Tetra/master/base/15994460412p0s2l6vbg/text.html на raw.githubusercontent.com

Вопрос:
using (SomeClass sc = new SomeClass()){}
Что делает данная конструкция?


Ответ:
Выражение using (в данном случае корректно говорить о нем как о
выражении) позволяет использовать в своем блоке кода некоторый ресурс (в
данном случае это класс) с последующим неявным вызовом метода Dispose
интерфейса IDisposable.


Для класса
class A: IDisposable
{
public void Dispose()
{ }
}


Данное выражение преобразуется компилятором в следующую конструкцию:
A a = new A();
try
{ }
finally
{
if (a != null)
{
((IDisposable)a).Dispose();
}
}


Так как класс, это ссылочный тип данных – в блоке finally компилятор добавит
проверку на null. Это справедливо также и для nullable значимых типов.
Только тогда компилятор добавит проверку на наличия значения:
Nullable<A> a = default(A);
Try { }
finally
{
if (a.HasValue)
{
((IDisposable)a.GetValueOrDefault()).Dispose();
}
}


Если же наш тип является значимым типом, не поддерживающим null, то
никаких проверок не будет:
A a = default(A);
try
{ }
finally
{
((IDisposable)a).Dispose();
}


Коварный вопрос:
Если наш значимый тип приводится к интерфейсу IDisposable, то ведь он
должен быть упакован и его копия должна быть перемещена в кучу. А так как
мы вызываем Dispose у копии, то, соответственно, у оригинала Dispose вызван
не будет.
Ответ:
Не во всех случаях приведение к типу интерфейса приводит к упаковке
значения – компилятор может использовать constrained оптимизацию.
Подробнее опкод constrained описан тут:
https://docs.microsoft.com/enus/dotnet/api/system.reflection.emit.opcodes.constrained?view=netcore-3.1


Коварный вопрос:
Чем отличается
A a = new A();
using(a)
{ }

От
using(A a = new A())
{ }

Это одно и тоже?
Ответ:
Нет, это не одно и тоже. Во втором случае все будет так, как описано выше, в
первом же случае внутри самого выражения using вы будете работать с
переменной
a, но Dispose будет вызван у копии данной переменной. Из этого
следует что первая запись некорректна.

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования