Наступні приклади коду забезпечують контекст мого запитання.
Клас 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, я змінюю конструктор на приватний та ввожу статичний заводський метод на ім'я 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
функція не захищає вас від отримання винятку при отриманні майна. Якщо ваш делегат кине, в реальному житті дуже ймовірно, що він кинеться лише за деяких умов. Ймовірно, що умов для метання немає під час будівництва, але вони є при отриманні майна.