这里已经有一些答案,但是这里的答案考虑了Unity3D(答案是非常特定于Unity3D的,在大多数情况下,我会以不同的方式进行大多数操作):
通常,Unity3D传统上不使用异常。如果您在Unity3D中引发异常,则不会像普通的.NET应用程序中那样,即它不会停止程序,因此您最多可以将编辑器配置为暂停。它将被记录下来。这很容易使游戏处于无效状态,并产生级联效应,使错误很难被追踪。因此,在Unity的情况下,Add
抛出异常是一个特别不可取的选择。
但是,在某些情况下,由于Mono在某些平台上如何在Unity中工作,因此在检查异常的速度时并不是某些情况下的过早优化。实际上,iOS上的Unity3D支持某些高级脚本优化,而禁用的例外*是其中之一的副作用。这确实是要考虑的事情,因为这些优化对许多用户而言已被证明是非常有价值的,这表明了考虑限制在Unity3D中使用异常的现实情况。(*来自引擎的托管异常,不是您的代码)
我想说的是,在Unity中,您可能想采用更专业的方法。具有讽刺意味的是,在撰写本文时,一个非常不赞成的答案表明了我可能会在Unity3D的上下文中专门实现这种方式的一种方式(在其他地方,这种方式确实是不可接受的,甚至在Unity中也相当不雅)。
我考虑的另一种方法实际上并不是在调用者关注的范围内指示错误,而是使用Debug.LogXX
函数。这样,您得到的行为与抛出未处理的异常(由于Unity3D如何处理它们)的行为相同,而不必冒险将某些事物置于异常状态。还要考虑这是否真的是错误的(在您的情况下尝试两次加载相同的材料必然会导致错误吗?或者这可能Debug.LogWarning
是更适用的情况)。
关于使用Debug.LogXX
函数而不是异常之类的东西,您仍然必须考虑当从返回值的东西(如GetMaterial)抛出异常时会发生什么。我倾向于通过传递null并记录错误来解决此问题(同样,仅在Unity中)。然后,我在MonoBehaviors中使用null检查,以确保像材料这样的任何依赖项都不是null值,如果是,则禁用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
可以在这里工作(**帮助程序的检查仅在Debug版本中编译(如asserts)。在Unity中使用lambda和表达式可能会降低性能)
_Materials.Add
引发异常?