10 марта 2020
Возможности C#
Среди всех новых возможностей C# 8, две из них относятся к достаточно актуальной теме освобождения ресурсов. Теперь конструкция using может использоваться асинхронно и для части структур. |
Асинхронное освобождение ресурсов (dispose)
C# 8 добавляет поддержку асинхронного освобождения ресурсов при помощи конструкции await using. Её использование аналогично обычному варианту using, но с поправкой на асинхронность:
await using (var x = new DisposableInstnace()) {
…
}
При этом класс, экземпляр которого передается в это выражение, должен реализовывать IAsyncDisposable. Единственный метод этого интерфейса является ответственным за освобождение необходимых ресурсов:
public interface IAsyncDisposable
{
ValueTask DisposeAsync();
}
Данный интерфейс используется для реализации другой новой возможности C# 8 – асинхронных потоков.
Поддержка освобождения ресурсов (dispose) для структур
Структуры, создаваемые только в стеке (ref struct) появились в C# 7.2. Они могут быть использованы для хранения неуправляемых или иных ресурсов, которые необходимо освободить как только они не будут нужны. Для класса в этом случае как правило используется конструкция using. Но для стуктур это не представляется возможным, так как они не поддерживают интерфейсы, а в данном случае требуется IDisposable.
C# 8 обходит это ограничение, используя “утиную типизацию”. Т.е. достаточно реализовать в структуре публичный метод void Dispose() и ее можно использовать в using.
Данная возможность применима к структурам объявленным как ref struct или readonly ref struct .
Пример:
internal ref struct Buffer<T>
{
public readonly T[] Data;
public Buffer(int size)
{
this.Data = ArrayPool<T>.Shared.Rent(size);
}
public void Dispose()
{
ArrayPool<T>.Shared.Return(this.Data, clearArray: true);
Console.WriteLine("Dispose() called.");
}
}
internal static class DisposableStructDemo
{
public static void Run()
{
using (var b = new Buffer<int>(42)) {
b.Data[0] = 42;
Console.WriteLine($"Data = {b.Data[0]}");
}
Console.WriteLine("Method completed.");
}
}