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

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

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

Опора — Раздел 24: исключения и модель отказа; Раздел 25: файлы и внешние данные. Дополнительно используются машинный числовой разбор из Раздела 11, форматирование через InvariantCulture из Раздела 8, методы и контракты из Раздела 13, массивы и строки из Разделов 15 и 19, структуры для результатов и диагностик из Раздела 20, систематическая локализация причины из Раздела 23.

Каждая задача оформляется отдельной консольной программой полным шаблоном курса и компилируется с <Nullable>enable</Nullable>. Разрешены только конструкции Разделов 1–25. Рабочие пути строятся через Path.Combine внутри отдельного каталога проекта; абсолютные пути, зависящие от компьютера ученика, не вшиваются в код. Разрешены File, Directory, Path, Encoding, чтение и запись целого текста или массива строк. Потоки, StreamReader, StreamWriter, using, IDisposable, двоичные форматы, FileSystemWatcher, коллекции, LINQ, пользовательские типы исключений, catch when и платформенные утверждения об атомарности запрещены. Ожидаемые ошибки содержимого обрабатываются через TryParse и явные результаты, а не через исключения. catch не остаётся пустым и не возвращает ложный успех: фиксируются тип отказа, контекст операции и сообщение. Действия finally проектируются так, чтобы не скрывать исходную причину новым необработанным исключением.


База практических заданий

Уровень I. Базовый

Место возникновения отказа, цепочка вызовов, расположение try, конкретный обработчик, путь, кодировка и состояние файлов заданы условием. Требуется точно проследить готовую политику, отделить обычный неуспех разбора от исключения и подтвердить состояние программы после каждого сценария. Ученик не выбирает границу обработки: сложность возрастает от распространения исключения к полному файловому конвейеру и подготовке результата до публикации.

1. Распространение по стеку вызовов: Построить цепочку:

static bool TryReadPositive(
    string text,
    out int value)

static bool TryLoadLimit(
    string text,
    out int limit)

static void RunScenario(string text)

TryReadPositive использует int.TryParse. Неверный формат возвращает false и value = 0, а неположительное корректное число приводит к:

throw new InvalidOperationException(
    "Limit must be positive.");

TryLoadLimit передаёт обычный неуспех наружу, а RunScenario выводит диагностическое сообщение для false. Ни один из методов не перехватывает InvalidOperationException. Main вызывает сценарий внутри try и обрабатывает только этот тип исключения. Для входов "12", "abc" и "0" записать обычный путь, место возникновения, прекращённые инструкции и кадры, покинутые до внешнего catch. Вывести тип, сообщение и StackTrace.

2. Конкретный обработчик и продолжение программы: Внутри try вызвать File.ReadAllText для гарантированно отсутствующего missing.txt. Обработать:

catch (FileNotFoundException exception)

Вывести:

  • exception.GetType().Name;
  • контекст «не удалось прочитать обязательный вход»;
  • exception.FileName;
  • exception.Message.

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

3. finally на обычном и аварийном пути: Реализовать метод, который получает путь и ref int attemptCount. В try он читает файл, устанавливает bool completed = true только после успешного чтения и возвращает текст. В finally увеличивает счётчик и выводит completed. Исключение внутри метода не перехватывается и обрабатывается в Main.

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

4. Повторная передача текущего исключения: Построить методы:

static string LoadRequiredText(string path)

static string LoadConfiguration(string path)

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

throw;

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

5. Рабочий каталог и переносимый путь: Получить текущий рабочий каталог через Environment.CurrentDirectory. Построить:

module14-data/input.txt

средствами Path.Combine. Если каталог module14-data отсутствует, создать его через Directory.CreateDirectory. Вывести:

  • относительный путь;
  • Path.GetFullPath;
  • Path.GetFileName;
  • Path.GetDirectoryName;
  • Path.GetExtension.

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

6. Полный текст и явная кодировка: Записать через File.WriteAllText и Encoding.UTF8 текст:

Alpha
Привет
Ω = 3.14

Прочитать его через File.ReadAllText с той же кодировкой, сравнить строки оператором == и вывести длины. Затем перезаписать файл строкой "second version" и подтвердить, что прежнее содержимое не дописывается. Проверить File.Exists до и после первой записи, не объявляя предварительную проверку гарантией будущей операции.

7. Массив строк и машинные числа: Записать через File.WriteAllLines строки:

10
-3
2.75
0.125

Прочитать через File.ReadAllLines. Первые две строки разобрать как int, последние две — как double с NumberStyles и CultureInfo.InvariantCulture. Неверный формат должен приводить к обычному результату false, номеру строки и отсутствию выходного отчёта, а не к исключению. При успехе вычислить сумму и записать отдельный файл в InvariantCulture.

8. Несколько обработчиков от конкретного к общему: Реализовать чтение обязательного файла и расположить обработчики:

catch (FileNotFoundException exception)
catch (DirectoryNotFoundException exception)
catch (UnauthorizedAccessException exception)
catch (IOException exception)

Проверить существующий файл, отсутствующий файл и путь с отсутствующим каталогом. Сценарий запрета доступа используется только в подготовленном окружении; если его нельзя воспроизвести переносимо, ограничение фиксируется без подмены другим исключением. Объяснить, почему FileNotFoundException и DirectoryNotFoundException должны находиться раньше общего обработчика IOException; UnauthorizedAccessException представляет отдельную ветвь иерархии.

9. Отчёт полностью в памяти: Дан массив структур:

public struct Measurement
{
    public DateTime Time;
    public double Value;
    public bool Accepted;
}

Сначала сформировать string[] отчёта: заголовок и по одной строке на запись. Использовать форматы:

  • время — yyyy-MM-ddTHH:mm:ss;
  • число — G17;
  • логическое поле — 0 или 1;
  • культура — InvariantCulture.

Только после построения всех строк вызвать File.WriteAllLines с Encoding.UTF8. Затем прочитать файл обратно и подтвердить точное поэлементное совпадение.

10. Конвейер «прочитать → разобрать → вычислить → записать»: Вход содержит строки:

id;value

где idint, а value — конечный double в InvariantCulture. Реализовать отдельные методы:

static string[] ReadInput(string path)

static bool TryParseRecords(
    string[] lines,
    out Record[] records,
    out int errorLine,
    out string errorMessage)

static Summary ComputeSummary(Record[] records)

static string[] FormatSummary(Summary summary)

static void WriteOutput(
    string path,
    string[] lines)

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

11. Сохранение существующего результата при ошибке данных: Целевой файл заранее содержит "confirmed". Входной файл проходит конвейер из I.10. Программа обязана полностью прочитать, разобрать, вычислить и сформировать string[] кандидата до вызова операции записи.

Для повреждённого входа подтвердить, что:

  • целевой файл по-прежнему существует;
  • его содержимое осталось "confirmed";
  • временный результат не публиковался.

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

12. Временный кандидат одного результата: Для того же конвейера использовать пути:

report.txt
report.tmp

Алгоритм задан:

  1. прочитать и проверить вход;
  2. сформировать весь результат в памяти;
  3. записать report.tmp;
  4. прочитать временный файл обратно и проверить точное содержимое;
  5. скопировать его в report.txt с перезаписью;
  6. удалить временный файл.

Очистка находится в finally и выполняется через внутренний try-catch, чтобы её отказ не скрывал основную причину. До шага копирования существующий report.txt должен оставаться неизменным. Не утверждать атомарность самого копирования или замены.


Уровень II. Продвинутый

Условие описывает возможные состояния ресурса и содержимого, но не задаёт границу try, набор обработчиков, способ возврата диагностик и допустимость частичного результата. Требуется самостоятельно разделить получение, проверку, вычисление и публикацию и выбрать, где операция продолжается, а где отменяется. В отличие от Уровня I ученик проектирует политику отказа и доказывает её согласованность для всех перечисленных сценариев.

1. Матрица ошибок и отказов: Для операций ниже составить таблицу с колонками тип ситуации → способ обнаружения → место решения → допустимое продолжение → состояние результата:

  • отсутствующее обязательное поле;
  • неверное число;
  • значение вне диапазона;
  • отсутствующий файл;
  • отсутствующий каталог;
  • запрет доступа;
  • иной IOException;
  • нарушение внутреннего предусловия метода.

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

2. Строгий файл конфигурации: Файл содержит ровно четыре непустые строки:

name=value

Обязательные уникальные имена:

width
height
threshold
mode

Самостоятельно спроектировать проверки:

  • число строк;
  • наличие одного разделителя;
  • пустое имя или значение;
  • неизвестное имя;
  • повтор;
  • отсутствие обязательного поля;
  • формат и диапазон чисел;
  • конечность threshold;
  • допустимое множество mode.

Любая ошибка содержимого отменяет всю конфигурацию и не является исключением. Исключение чтения обрабатывается на внешней границе.

3. Смешанный журнал измерений: Файл содержит:

timestamp;value

а также пустые и повреждённые строки. Время разбирается точным форматом yyyy-MM-ddTHH:mm:ss, число — через InvariantCulture. Спроектировать:

  • массив корректных записей точного размера;
  • массив диагностик с номером строки и причиной;
  • статистику только корректных конечных значений;
  • отдельный отчёт об ошибках.

Файловый отказ прекращает всю операцию; ошибка отдельной строки не прекращает разбор. Публикация двух отчётов выполняется только после завершения анализа всего входа.

4. Агрегирование каталога: В заданном каталоге находятся текстовые файлы с целыми числами по одному в строке. Получить пути через Directory.GetFiles, процедурно отсортировать их по StringComparison.Ordinal и обработать каждый файл независимо.

Для каждого файла сохранить либо:

  • число значений и сумму;
  • тип файлового отказа;
  • номера и причины повреждённых строк.

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

5. Обязательные части одного документа: Три файла содержат заголовок, тело и заключение. Итог разрешено публиковать только при успешном чтении всех частей. Самостоятельно определить:

  • методы чтения;
  • границу try;
  • конкретные обработчики;
  • порядок объединения;
  • проверку непустого заголовка и заключения;
  • формирование результата в памяти.

При любом файловом отказе или ошибке содержимого существующий итоговый файл остаётся неизменным.

6. Порог ошибок импорта: Файл содержит:

id;amount

где amountdecimal в InvariantCulture. Корректные записи и диагностики повреждённых строк накапливаются раздельно. Если число ошибок превышает maxErrors, основной результат не публикуется.

Самостоятельно определить:

  • продолжать ли анализ после превышения порога;
  • какие сведения обязаны сохраниться;
  • состояние выходных файлов при maxErrors = 0;
  • отличие «частичный импорт разрешён» от «вся операция отменена».

Выбранная политика фиксируется до реализации и одинаково применяется ко всем строкам.

7. Граница обработки в цепочке методов: Спроектировать уровни:

static string ReadRequiredText(string path)

static bool TryParseDocument(
    string text,
    out Document document,
    out string error)

static bool TryRunOperation(
    string path,
    out Result result,
    out string dataError)

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

Показать успешный файл, повреждённый файл и отсутствующий файл.

8. Явная кодировка и содержательная проверка: Один вход записан в UTF-8, второй — в UTF-16 через Encoding.Unicode. Каждый читается с заявленной кодировкой, затем проходит проверку контрольной строки с кириллицей и Ω. После нормализации формируется общий UTF-8-отчёт.

В отдельном запуске намеренно применить неверную кодировку. Если API возвращает строку без исключения, но контрольная фраза нарушена, классифицировать результат как ошибку содержимого. Объяснить, почему успешное чтение байтов не гарантирует правильной интерпретации текста.

9. Продолжение независимого пакета: Даны несколько входных файлов одного формата. Каждый файл является независимой операцией и может породить собственный результат. Спроектировать пакет, который:

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

Разделить статусы CompleteSuccess, PartialSuccess и Failure через enum.

10. Временный кандидат и отказ очистки: Целевой файл содержит подтверждённую версию. Преобразование записывает временный кандидат, проверяет его чтением и затем копирует в целевой путь. В finally выполняется удаление временного файла.

Спроектировать вложенную обработку очистки так, чтобы различались:

  • основная операция успешна, очистка успешна;
  • основная операция успешна, очистка неуспешна;
  • основная операция неуспешна, очистка успешна;
  • основная операция неуспешна, очистка тоже неуспешна.

Отказ очистки сообщается отдельно и не заменяет исходное исключение основной операции. Если среда не позволяет переносимо вызвать отказ File.Delete, он воспроизводится параметром тестового сценария, который перед удалением намеренно бросает IOException.

11. Один итог по нескольким входам: Несколько входных файлов образуют один сводный отчёт. Каждый читается и разбирается независимо, но публикация разрешена только при полном успехе всего набора.

Спроектировать:

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

При ошибке вывести все обнаруженные проблемы, а не только первую, если дальнейшее чтение безопасно.

12. Несколько выходов и подготовительная фаза: Три входных файла должны породить:

  • один сводный отчёт;
  • три нормализованные копии.

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

До реализации перечислить допустимые состояния после отказа:

  • до подготовки;
  • во время подготовки;
  • между фиксациями;
  • после полной фиксации.

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


Уровень III. Экспертный

Исследуется не отдельный catch, а доказуемая гарантия всей операции. До запуска требуется указать место искусственного или реального отказа, путь разворачивания стека и состояние каждого постоянного и временного файла. После запуска формулируется максимально сильное утверждение, которое действительно обеспечивает протокол, и отдельно перечисляются состояния, которые он не исключает.

1. throw; и throw exception;: Построить цепочку из трёх методов. Нижний читает отсутствующий файл. Средний в двух отдельных версиях выполняет:

throw;

и:

throw exception;

До запуска предсказать, где будет начинаться сохранённая трасса повторно переданного исключения. После сравнить StackTrace и объяснить, почему throw; сохраняет исходную точку возникновения, а явный повторный бросок переменной изменяет диагностическую историю.

2. Предварительная проверка и изменение ресурса: Для существующего файла выполнить File.Exists(path), затем намеренно удалить его до File.ReadAllText(path). В отдельном допустимом окружении после проверки заменить файл каталогом с тем же путём.

До запуска записать:

  • результат проверки;
  • ожидаемое состояние ресурса перед чтением;
  • тип возможного отказа;
  • состояние результата.

После доказать, что проверка помогает раннему ветвлению, но не создаёт блокировки и не гарантирует успех последующей операции.

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

static bool TryLoad(
    string path,
    out string text)
{
    try
    {
        text = File.ReadAllText(path);
        return true;
    }
    catch (Exception)
    {
        text = string.Empty;
        return true;
    }
}

Для отсутствующего файла вызывающий код получает успех и пустой документ. Проследить потерю типа и причины отказа. Переработать контракт так, чтобы:

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

4. Исключение из finally, скрывающее исходную причину: В try прочитать отсутствующий файл, а в finally записать текст в путь с отсутствующим каталогом. До запуска предсказать два отказа и определить, какой достигнет внешнего catch.

После показать, что исключение из finally заменяет распространявшийся FileNotFoundException. Переработать очистку через внутренний try-catch, который сообщает вторичный отказ, но позволяет исходному исключению продолжить распространение.

5. Частичная прямая запись и временная подготовка: Сформировать отчёт из десяти строк двумя способами. После подготовки пятой строки вызвать:

throw new IOException(
    "Injected failure");

Первая версия после каждой итерации перезаписывает целевой файл текущим накопленным префиксом. Вторая версия изменяет только временный файл, а целевой затрагивает после полной подготовки.

До запуска зафиксировать исходное содержимое цели. После сравнить постоянные и временные файлы. Доказать сохранение цели при отказе до фиксации во второй схеме и не приписывать атомарность последующей операции копирования.

6. Матрица искусственных отказов конвейера: Объявить:

enum FailurePoint
{
    None,
    BeforeRead,
    AfterRead,
    AfterParse,
    AfterCompute,
    AfterFormat,
    AfterTemporaryWrite,
    BeforeCommit,
    AfterCommit,
    DuringCleanup
}

Реализовать один файловый конвейер и отдельный метод:

static void InjectFailure(
    FailurePoint current,
    FailurePoint selected)

который при совпадении бросает IOException. Для каждого значения перечисления выполнить отдельный запуск и записать:

  • достигнутые этапы;
  • созданные временные файлы;
  • содержимое цели;
  • исключение внешней границы;
  • результат очистки.

BeforeCommit срабатывает непосредственно перед вызовом фиксации, а AfterCommit — сразу после его успешного возврата. Искусственная функция не способна внедриться внутрь одного библиотечного вызова, поэтому реальный отказ самой фиксации исследуется отдельно как неподконтрольный файловый отказ. Сформулировать инвариант: до входа в этап фиксации подтверждённая цель не изменяется.

7. Попытка отката тоже может отказать: Сравнить две схемы публикации нескольких файлов:

  1. последовательная замена без резервных копий;
  2. создание резервных копий, последовательная замена и попытка восстановления при отказе.

Инъекцией отказа исследовать:

  • отказ до первой фиксации;
  • отказ между двумя фиксациями;
  • отказ во время восстановления.

Показать, что резервная копия расширяет возможности восстановления, но не превращает пользовательский код в доказанную транзакцию: откат сам является файловой операцией и может завершиться неуспешно.

8. Доказательство максимально сильной гарантии: Спроектировать законченный протокол публикации одного целевого файла:

  1. прочитать вход;
  2. проверить содержимое;
  3. вычислить результат;
  4. сформировать текст;
  5. записать временный кандидат в каталоге цели;
  6. прочитать и проверить кандидат;
  7. выполнить одну операцию фиксации;
  8. очистить остатки.

Для каждого перехода построить таблицу:

  • предусловие;
  • возможный отказ;
  • состояние входа;
  • состояние старой цели;
  • состояние временного файла;
  • доступная стратегия восстановления.

Затем сформулировать отдельно:

  • что гарантируется до начала фиксации;
  • что наблюдалось в конкретной среде;
  • что не доказано без платформенной гарантии;
  • какие сведения нужны оператору для ручного восстановления.

Задача оценивается по точности границ утверждения, а не по обещанию абсолютной безопасности.


Обязательные контрольные наборы

ЗадачаПодготовленные данные и сценарии
I.1"12", "abc", "0"
I.2гарантированно отсутствующий missing.txt
I.3один существующий и один отсутствующий файл; счётчик 0
I.4отсутствующий файл конфигурации и цепочка из двух методов
I.5каталог module14-data, файл input.txt
I.6"Alpha\nПривет\nΩ = 3.14" и "second version"
I.7строки 10, -3, 2.75, 0.125; затем повреждённая третья строка
I.8существующий файл, отсутствующий файл, отсутствующий каталог и подготовленный недоступный путь
I.9не менее трёх измерений, включая отрицательное и непринятое
I.10корректный файл; повреждённые id, value; NaN; пустая строка
I.11целевой файл "confirmed"; корректный и повреждённый вход
I.12существующий report.txt, успешный кандидат и искусственный отказ до копирования
II.1все восемь ситуаций из таблицы
II.2корректный набор; повтор width; отсутствующий mode; threshold = NaN; неизвестное имя
II.3корректные записи, пустая строка, неверная дата, неверное число, лишнее поле
II.4два корректных файла, повреждённый файл и отсутствующий путь
II.5три существующие части; отсутствующее тело; пустое заключение; существующий итог
II.6maxErrors = 0,2,5; не менее четырёх повреждённых строк
II.7корректный, повреждённый и отсутствующий документ
II.8одна контрольная фраза в UTF-8 и UTF-16; неверно заявленная кодировка
II.9три файла: успешный, повреждённый и отсутствующий
II.10все четыре сочетания основной операции и очистки
II.11три корректных входа; затем ошибки в первом и третьем
II.12четыре существующие цели; отказ подготовки и отказ между фиксациями
III.1один отсутствующий файл; две версии повторной передачи
III.2существующий файл, удаляемый между проверкой и чтением
III.3пустой корректный файл и отсутствующий файл
III.4отсутствующий вход и путь очистки внутри отсутствующего каталога
III.5цель "confirmed" и отказ после пятой строки
III.6все значения FailurePoint в отдельных запусках
III.7три целевых файла; отказы до фиксации, между фиксациями и при восстановлении
III.8корректный и повреждённый вход; отказ каждого этапа из таблицы

Итог модуля

Ученик прослеживает возникновение и распространение исключения по стеку, размещает конкретные обработчики на границе осмысленного решения, применяет finally без потери исходной причины и повторно передаёт текущий отказ через throw;. Он отличает проверяемую ошибку содержимого от исключительной невозможности выполнить операцию, строит переносимые пути, явно задаёт кодировку и культуру и разделяет чтение, разбор, вычисление, форматирование и запись. Публикация начинается только после полной подготовки и проверки кандидата; временные файлы, очистка, частичные результаты, пакетная обработка и искусственные отказы рассматриваются как состояния протокола. Гарантии формулируются только для реально доказанных этапов: предварительная проверка не гарантирует последующее использование ресурса, а подготовка временного файла не объявляется атомарной транзакцией одного или нескольких постоянных файлов.

Покрытие опоры и границы

  • Место возникновения исключения, прекращение обычного пути и разворачивание стека: I.1–I.4, II.7, III.1, III.4.
  • try, конкретные catch, несколько обработчиков и диагностическая информация: I.2–I.4, I.8, II.1, II.4–II.7, III.3–III.4.
  • finally, обычный и аварийный выход, отказ очистки: I.3, I.12, II.10, III.4, III.6, III.8.
  • throw и повторное распространение через throw;: I.1, I.4, II.1, III.1, III.6.
  • Ожидаемая ошибка данных против исключительной ситуации: I.1, I.7, I.10–I.11, II.1–II.3, II.6–II.9, III.3.
  • Запрет пустого и чрезмерно широкого обработчика: I.2, I.8, II.1, II.7, III.3.
  • Относительные и абсолютные пути, текущий каталог и Path.Combine: I.5, I.12.
  • Создание каталога и перечисление файлов: I.5, II.4.
  • Чтение и запись полного текста и массива строк: I.6–I.12, II.2–II.12.
  • Кодировка и содержательная проверка текста: I.6, I.9, II.8.
  • Машинный числовой формат и InvariantCulture: I.7, I.9–I.10, II.2–II.3, II.6.
  • Разделение файлового ввода-вывода, разбора, вычисления и представления: I.9–I.12, II.2–II.12, III.5–III.8.
  • File.Exists и отсутствие гарантии последующей операции: I.6, III.2.
  • Подготовка результата до изменения цели: I.9–I.12, II.3, II.5–II.6, II.10–II.12, III.5–III.8.
  • Временный кандидат и проверка перед фиксацией: I.12, II.10–II.12, III.5–III.8.
  • Политика частичного результата и пакетная обработка: II.3–II.6, II.9, II.11–II.12, III.7.
  • Искусственная инъекция отказов и анализ состояния: III.5–III.8.
  • Граница доказуемой согласованности и отказ от неподтверждённой атомарности: II.12, III.5–III.8.

За границей: пользовательские типы исключений, фильтры catch when, систематическое управление ресурсами через IDisposable, потоки, StreamReader, StreamWriter, асинхронный ввод-вывод, двоичные форматы, блокировки файлов, права доступа разных платформ, журналирование транзакций и гарантии атомарной замены относятся к последующим курсам. Модуль не утверждает, что временный файл, резервная копия или проверка существования устраняют все отказы: они только усиливают явно доказанную политику для определённых этапов операции.