Il y a déjà quelques réponses ici, mais voici la réponse qui prend Unity3D en compte (la réponse est très spécifique à Unity3D, je ferais la plupart de ces choses très différemment dans la plupart des contextes):
En général, Unity3D n'utilise pas les exceptions de manière traditionnelle. Si vous générez une exception dans Unity3D, ce n'est pas comme dans votre application .NET moyenne, à savoir que cela n'arrête pas le programme, vous pouvez configurer l'éditeur pour qu'il suspende. Il suffit de vous connecter. Cela peut facilement mettre le jeu dans un état non valide et créer un effet de cascade rendant les erreurs difficiles à localiser. Donc, je dirais que dans le cas de Unity, laisser Add
une exception est une option particulièrement indésirable.
Toutefois, l'examen de la vitesse des exceptions ne constitue pas un cas d'optimisation prématurée dans certains cas, en raison du fonctionnement de Mono dans Unity sur certaines plates-formes. En fait, Unity3D sur iOS prend en charge certaines optimisations de script avancées, et les exceptions désactivées * constituent l'un des effets secondaires de l'une d'entre elles. C’est vraiment quelque chose à prendre en compte car ces optimisations se sont révélées très utiles pour de nombreux utilisateurs, ce qui représente un cas réaliste pour envisager de limiter l’utilisation des exceptions dans Unity3D. (* exceptions gérées du moteur, pas votre code)
Je dirais que dans Unity, vous voudrez peut-être adopter une approche plus spécialisée. Ironiquement, une réponse très votée au moment de la rédaction montre que je pourrais implémenter un tel système, notamment dans le contexte d’Unity3D (ailleurs, il est vraiment inacceptable, et même dans Unity, il est assez inélégant).
Une autre approche que je considérerais en réalité n’indique pas une erreur en ce qui concerne l’appelant, mais utilise plutôt les Debug.LogXX
fonctions. De cette façon, vous obtenez le même comportement que de lancer une exception non gérée (à cause de la façon dont Unity3D les gère) sans risquer de placer quelque chose dans un état étrange en bout de ligne. Déterminez également s’il s’agit vraiment d’une erreur (essayer de charger deux fois le même matériel est-il nécessairement une erreur dans votre cas? Ou peut-être est-ce un cas où cela Debug.LogWarning
s’applique plus).
Et en ce qui concerne l'utilisation d'éléments tels que des Debug.LogXX
fonctions plutôt que des exceptions, vous devez toujours considérer ce qui se produit lorsqu'une exception serait levée à partir de quelque chose qui retourne une valeur (comme GetMaterial). J'ai tendance à aborder ceci en passant null avec l'enregistrement de l'erreur ( encore une fois, uniquement dans Unity ). J'utilise ensuite des contrôles nuls dans MonoBehaviors pour garantir que toute dépendance, telle qu'un matériau, n'est pas une valeur nulle, et désactive le MonoBehavior si c'est le cas. Voici un exemple de comportement simple nécessitant quelques dépendances:
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<>
est similaire à votre exemple en ce sens qu'il appelle une fonction sur un dictionnaire qui lève une exception. Mais au lieu de lancer une exception, il utilise Debug.LogError
une trace de pile, comme une exception normale, et renvoie null. Les vérifications qui suivent * désactiveront le comportement au lieu de le laisser continuer d'exister dans un état non valide.
* les contrôles ressemblent à cela à cause d'un petit assistant que j'utilise qui imprime un message formaté lorsqu'il désactive l'objet du jeu **. Des contrôles nuls simples avec if
travail ici (** les contrôles de l'assistant sont uniquement compilés dans des versions Debug (comme des assertions. L'utilisation de lambdas et d'expressions comme celle-là dans Unity peut nuire à la performance)
_Materials.Add
jette une exception?