Сообщения об ошибках должны быть записаны в stderr, иначе Console.Error, и нормально выводиться в стандартный вывод, также известный как Console.Out. Это особенно важно для консольных приложений типа «фильтр», чей вывод (stdout) может быть передан другому процессу, например, в командном файле.
Обычно, если вы столкнулись с ошибкой, напишите сообщение об ошибке в Console.Error и верните ненулевой результат. Или, если это исключение, просто не беспокойтесь об этом.
Чтобы вернуть код результата, вы можете передать его в качестве аргумента в Environment.Exit, установить свойство Environment.ExitCode или вернуть ненулевое значение из main.
Для простых консольных приложений я бы:
имеет вспомогательный класс для разбора командной строки.
имеет класс фасадов, который предоставляет тестируемый API для функциональности, реализованной вашим инструментом командной строки. Как и для большинства .NET API, при возникновении ошибки обычно выдается исключение.
основная программа просто использует помощник для анализа командной строки и вызывает API, передавая аргументы, переданные из командной строки. Он может перехватывать исключения, генерируемые API, регистрировать их, записывать пользовательское сообщение об ошибке в Console.Error и устанавливать ненулевой код возврата.
Но я не считаю, что это единственно верный путь: на самом деле такого нет, поэтому вряд ли вы найдете книгу, которую ищете.