Já existem algumas respostas aqui, mas aqui está a resposta que leva em consideração o Unity3D (a resposta é muito específica para o Unity3D, eu faria isso muito diferentemente na maioria dos contextos):
Em geral, o Unity3D não usa exceções tradicionalmente. Se você lançar uma exceção no Unity3D, não será como em um aplicativo .NET comum, a saber, não interromperá o programa, na maioria das vezes você poderá configurar o editor para pausar. Apenas será registrado. Isso pode facilmente colocar o jogo em um estado inválido e criar um efeito em cascata que dificulta o rastreamento dos erros. Então, eu diria que, no caso da Unity, deixar Add
lançar uma exceção é uma opção especialmente indesejável.
Mas examinar a velocidade das exceções não é um caso de otimização prematura em alguns casos, devido ao modo como o Mono funciona no Unity em algumas plataformas. De fato, o Unity3D no iOS suporta algumas otimizações avançadas de script, e as exceções desabilitadas * são um efeito colateral de uma delas. Isso é realmente algo a considerar, porque essas otimizações se mostraram muito valiosas para muitos usuários, mostrando um argumento realista para considerar a limitação do uso de exceções no Unity3D. (* exceções gerenciadas do mecanismo, não seu código)
Eu diria que no Unity você pode querer adotar uma abordagem mais especializada. Ironicamente, um muito baixo votado resposta no momento da escrita deste , mostra uma maneira que eu poderia implementar algo parecido com isto especificamente no contexto da Unity3D (em outro lugar algo como isso realmente é inaceitável, e até mesmo em Unity é bastante deselegante).
Outra abordagem que eu consideraria na verdade não é indicar um erro no que diz respeito ao chamador, mas usar as Debug.LogXX
funções. Dessa forma, você obtém o mesmo comportamento de lançar uma exceção não tratada (por causa de como o Unity3D lida com eles) sem correr o risco de colocar algo em um estado estranho na linha. Considere também se isso realmente é um erro (a tentativa de carregar o mesmo material duas vezes necessariamente é um erro no seu caso? Ou pode ser um caso onde Debug.LogWarning
é mais aplicável).
E no que diz respeito ao uso de coisas como Debug.LogXX
funções em vez de exceções, você ainda precisa considerar o que acontece quando uma exceção é lançada de algo que retorna um valor (como GetMaterial). Eu costumo abordar isso passando nulo junto com o log do erro ( novamente, apenas no Unity ). Em seguida, uso verificações nulas em meus MonoBehaviors para garantir que qualquer dependência, como um material, não seja um valor nulo e desabilito o MonoBehavior, se for o caso. Um exemplo para um comportamento simples que requer algumas dependências é algo como isto:
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<>
é semelhante ao seu exemplo, pois chama uma função em um dicionário que gera uma exceção. Mas, em vez de lançar uma exceção, ele usa, Debug.LogError
que fornece um rastreamento de pilha como uma exceção normal faria e retornaria nulo. As verificações a seguir * desabilitarão o comportamento em vez de permitir que ele continue a existir em um estado inválido.
* os cheques se parecem com isso por causa de um pequeno auxiliar que eu uso que imprime uma mensagem formatada quando desativa o objeto do jogo **. Verificações nulas simples com if
trabalho aqui (** as verificações do auxiliar são compiladas apenas nas compilações de depuração (como afirmações). O uso de lambdas e expressões como essa no Unity pode prejudicar o desempenho)
_Materials.Add
lançar uma exceção?