Тут вже є кілька відповідей, але ось відповідь, яка враховує Unity3D (відповідь дуже специфічна для Unity3D, я б зробив більшість цього зовсім по-різному в більшості контекстів):
Загалом, Unity3D традиційно не використовує винятків. Якщо ви викинете виняток у Unity3D, він не схожий на ваш середній додаток .NET, а саме він не зупинить програму, t більшість ви можете налаштувати редактор на паузу. Він просто зареєструється. Це може легко поставити гру в недійсний стан і створити ефект каскаду, що ускладнює відстеження помилок. Тому я б сказав, що у випадку Unity, дозволити Addвикинути виняток є особливо небажаним варіантом.
Але при вивченні швидкості виключень в деяких випадках не відбувається передчасної оптимізації через те, як Mono працює в Unity на деяких платформах. Насправді Unity3D на iOS підтримує деякі розширені оптимізації сценаріїв, а виключені виключення * є побічним ефектом одного з них. Це дійсно щось, що слід враховувати, оскільки ці оптимізації виявились дуже цінними для багатьох користувачів, показуючи реалістичний випадок розгляду обмеження на використання винятків у Unity3D. (* керовані винятки з двигуна, а не ваш код)
Я б сказав, що в Unity ви можете скористатися більш спеціалізованим підходом. За іронією долі, на момент написання цього запиту, дуже невдоволена відповідь , показує один із способів, як я можу реалізувати щось подібне конкретно в контексті Unity3D (в інших місцях щось подібне насправді неприйнятно, і навіть в Unity це досить неелегантно).
Ще один підхід, який я вважаю, насправді не вказує на помилку, що стосується абонента, а скоріше використання Debug.LogXXфункцій. Таким чином, ви отримуєте таку саму поведінку, як кидати необроблений виняток (через те, як Unity3D поводиться з ними), не ризикуючи поставити щось у дивному стані вниз. Також врахуйте, чи справді це помилка (намагається завантажити один і той же матеріал двічі, обов'язково помилка у вашому випадку? Або це може бути випадок, коли Debug.LogWarningце більше стосується).
Що стосується використання таких речей, як Debug.LogXXфункції, а не винятки, вам все одно доведеться враховувати, що відбувається, коли виняток буде викинуто з чогось, що повертає значення (наприклад, GetMaterial). Я схильний підходити до цього, передаючи null разом із реєстрацією помилки ( знову ж таки, лише в Unity ). Тоді я використовую нульові перевірки в моїх MonoBehaviors, щоб гарантувати, що будь-яка залежність, наприклад, матеріал не є нульовим значенням, і відключаю MonoBehavior, якщо він є. Приклад простої поведінки, яка вимагає декількох залежностей, є приблизно таким:
public void Awake()
{
_inputParameters = GetComponent<VehicleInputParameters>();
_rigidbody = GetComponent<Rigidbody>();
_rigidbodyTransform = _rigidbody.transform;
_raycastStrategySelector = GetComponent<RaycastStrategySelectionBehavior>();
_trackParameters =
SceneManager.InstanceOf.CurrentSceneData.GetValue<TrackParameters>();
this.DisableIfNull(() => _rigidbody);
this.DisableIfNull(() => _raycastStrategySelector);
this.DisableIfNull(() => _inputParameters);
this.DisableIfNull(() => _trackParameters);
}
SceneData.GetValue<>подібний вашому прикладу тим, що він викликає функцію у словнику, яка видає виняток. Але замість того, щоб викидати виняток, він використовує, Debug.LogErrorщо дає слід стека, як звичайний виняток, і повертає null. Наступні перевірки * відключать поведінку замість того, щоб продовжувати існувати у недійсному стані.
* чеки виглядають так через маленького помічника, який використовує, який виводить форматоване повідомлення, коли він відключає ігровий об’єкт **. Прості нульові перевірки з ifроботою тут (** перевірки помічників збираються лише у налагодженнях налагодження (наприклад, твердження). Використання лямбдів і виразів, подібних до Unity, може спричинити справність)
_Materials.Addкинути виняток?