Следующие примеры кода предоставляют контекст для моего вопроса.
Класс комнаты инициализируется с делегатом. В первой реализации класса Room нет защиты от делегатов, которые генерируют исключения. Такие исключения будут пузыриться до свойства North, где оценивается делегат (примечание: метод Main () демонстрирует, как экземпляр Room используется в клиентском коде):
public sealed class Room
{
private readonly Func<Room> north;
public Room(Func<Room> north)
{
this.north = north;
}
public Room North
{
get
{
return this.north();
}
}
public static void Main(string[] args)
{
Func<Room> evilDelegate = () => { throw new Exception(); };
var kitchen = new Room(north: evilDelegate);
var room = kitchen.North; //<----this will throw
}
}
Поскольку я предпочел бы потерпеть неудачу при создании объекта, а не при чтении свойства North, я изменил конструктор на private и ввел статический фабричный метод с именем Create (). Этот метод перехватывает исключение, выданное делегатом, и генерирует исключение оболочки, имеющее значимое сообщение об исключении:
public sealed class Room
{
private readonly Func<Room> north;
private Room(Func<Room> north)
{
this.north = north;
}
public Room North
{
get
{
return this.north();
}
}
public static Room Create(Func<Room> north)
{
try
{
north?.Invoke();
}
catch (Exception e)
{
throw new Exception(
message: "Initialized with an evil delegate!", innerException: e);
}
return new Room(north);
}
public static void Main(string[] args)
{
Func<Room> evilDelegate = () => { throw new Exception(); };
var kitchen = Room.Create(north: evilDelegate); //<----this will throw
var room = kitchen.North;
}
}
Оказывает ли блок try-catch метод Create () нечистым?
Create
, также нечист, потому что он ее вызывает.
Create
функция не защищает вас от получения исключения при получении имущества. Если ваш делегат бросит, в реальной жизни очень вероятно, что он будет брошен только при определенных условиях. Скорее всего, условия для броска отсутствуют во время строительства, но они присутствуют при получении имущества.