resource-cleanup використовує інтерфейс IDispose, щоб позначити, що ресурс якогось обʼєкта або інший стан програми потрібно звільнити чи скинути, коли обʼєкт більше не потрібен (і що покладатися на збирач сміття не дасть цього результату чи потрібного рівня контролю), а також що метод IDisposable.Dispose() був природним місцем для таких операцій очищення.
Є й інша конструкція, блок using, яка дає змогу з погляду того, хто викликає код, зібрати все керування часом життя ресурсів в одну інструкцію.
using (var file = new File("my_secrets"))
{
file.WriteSecret("xxxxxxx");
}
У наведеному вище прикладі ресурси файлової системи, повʼязані з file, будуть звільнені й повернуті операційній системі, коли виконання виходить за межі блоку using.
Щоб ця конструкція працювала, змінна в інструкції using має бути посилального типу, який реалізує інтерфейс IDisposable, і має звільняти ресурси та скидати стан програми у своєму методі Dispose().
C# 8 пропонує удосконалення цієї конструкції. Інструкцію using можна розмістити на початку блоку.
using var drawingResource = some_provided_or_new_object;
try
{
drawingResource.DrawSomething();
}
catch (Exception)
{
throw;
}
Розробники Java можуть упізнати в цьому аналог механізму автоматичного керування ресурсами, запровадженого в Java 7.
Ми знову працюємо над системою ORM (обʼєктно-реляційне відображення), представленою в object-relational-mapping.
Аналіз використання нашої ORM показує, що 95% транзакцій виконуються з одного методу, який їх викликає, і було вирішено, що доцільніше мати один метод ORM, який відкриває, записує та фіксує транзакцію.
База даних має такі методи екземпляра:
Database.BeginTransaction() починає транзакцію в базі даних.Database.Write(string data) записує дані до бази даних у межах транзакції. Якщо вона отримає некоректні дані, буде викинуто виняток. Спроба викликати цей метод без попереднього виклику BeginTransaction() спричинить викидання винятку. У разі успіху внутрішній стан бази даних зміниться на DataWritten.Database.EndTransaction() фіксує транзакцію в базі даних. Він може викинути виняток, якщо не вдасться закрити транзакцію або якщо Database.BeginTransaction() не було викликано.Database.Dispose() очистить базу даних, якщо під час транзакції буде викинуто виняток. Це змінить стан бази даних на Closed.Реалізуйте метод Orm.Write(), щоб почати транзакцію бази даних, записати передані дані та зафіксувати транзакцію. Усі винятки, зокрема InvalidOperationException, мають передаватися тому, хто викликав метод, без логування чи будь-якого іншого втручання.
Database db = new Database();
Orm orm = new Orm(db);
orm.Write("good write");
// => database has an internal state of State.Closed
orm.Write("bad write");
// => an exception is thrown but database is left with an internal state of State.Closed
orm.Write("bad commit");
// => an exception is thrown but database is left with an internal state of State.Closed
Минуло кілька місяців відтоді, як було додано Orm.Write(), і в команді немає одностайності. Багато розробників хотіли б, щоб ORM обробляла помилки, коли викидається виняток, і просто повертала тому, хто викликав, ознаку успіху.
Будь ласка, реалізуйте метод Orm.WriteSafely(), щоб почати транзакцію бази даних, записати передані дані та зафіксувати транзакцію (як описано вище). Він має повертати true, якщо запис був успішним, інакше false. Не намагайтеся логувати виняток.
Database db = new Database();
Orm orm = new Orm(db);
orm.WriteSafely("good write");
// => true
orm.WriteSafely("bad write");
// => false
orm.WriteSafely("bad commit");
// => false
Зареєструйтеся на Exercism, щоб вивчати й опановувати C#, а також 62 концепції178 вправ та справжнє наставництво від людей, і все це безкоштовно.