Вариант 3, который вы всегда должны делать, независимо от выбранного вами подхода, для представления ошибок пользователям - конечно, если это разумно достижимо, т. Е. Если у вас есть доступ для записи в хранилище, достаточно большое для хранения журналов.
Выбор между 1 и 2 зависит от общего подхода, который вы выбираете для предоставления информации об ошибках своим пользователям. В мире .NET выбрасывание исключений является предпочтительным, по крайней мере, в стандартных ситуациях, и под стандартом я имею в виду синхронность вашего интерфейса. Если ваши пользователи вызывают метод вашего класса и ждут, когда вы вернете значение (или просто закончите выполнение), вы должны выбросить исключение, если что-то не так «достаточно»
В некоторых случаях вам может потребоваться отказаться от создания исключений, например, если интерфейс, который вы предоставляете клиентам, является асинхронным. Если они вызывают ваш метод, и вы сразу же возвращаетесь, оставляя рабочий поток в фоновом режиме - тогда выбрасывать исключения просто не вариант, и вам нужно добавить аналогичный подход, основанный на событиях, чтобы позволить вашим клиентам подписываться на информацию об ошибках - если им это нужно ! Это то, что вам нужно решить (если только вы не опубликуете более подробную информацию о характере вашего проекта) - если вы можете сойти с рук, просто регистрируя ошибки в файле, зачем беспокоиться о возбуждении событий?
Существует еще одна причина, по которой вам может потребоваться реализовать уведомления об ошибках, не основанные на исключениях. У вас все еще может быть синхронная модель - клиенты звонят вам и ждут завершения вашей операции - и затем вы можете (и вам следует) использовать события для уведомления вызывающей стороны о том, что операция не может быть успешно завершена. Но у вас может быть различие между чем-то, что происходит «достаточно неправильно» и «слегка неправильно». Рассмотрим следующий сценарий:
Клиент вызывает метод, вы запускаете асинхронную операцию, но в какой-то момент начинаете ждать ее завершения, например, с Thread.Join
или WaitHandle.WaitOne
. Когда рабочий поток в конце концов завершается, вы возвращаете результат пользователю. Вы можете подписаться на событие ошибки из базовой структуры - но вы можете идентифицировать эту ошибку как не фатальную, поэтому вместо генерации исключения вы можете продолжить ожидание завершения фонового потока, но в любом случае уведомить пользователя об ошибке ( опять же - только если вам нужно, довольно часто вы можете уйти, просто войдя в систему). Это можно сделать либо с помощью событий, либо с помощью возвращаемого значения (или параметра ref
/ out
). Последний является более распространенным подходом - вы просто возвращаете список несмертельных ошибок, которые в большинстве случаев будут пустыми, и, если клиенту не все равно, - он пойдет по списку.
Вот и все, в основном это зависит от интерфейса вашей библиотеки классов - является ли он синхронным или нет, если вы поделитесь более подробной информацией о том, что вы можете получить более конкретные ответы.