.NET错误处理:try / catch VS事件VS return-value / status-fields

时间:2012-07-03 19:35:39

标签: c# .net visual-studio-2010 xamarin.android

我现在处于跨平台移动应用开发的十分重要的交叉路上,可以真正使用一些专业知识(如woah)。

为了给出一些背景信息(这可能有助于回答我的希望),我正在使用VS2010U(不是MonoDevelop,用于IOS)开发基于方便的MonoCross框架的.NET移动应用程序。第一个目标平台是Android,然后是IOS和Windows Phone“端口”(如果我做对了,那就不是真的了。)

现在我已经奠定了坚实的基础,包括业务逻辑,数据访问层,数据库,REST Web服务等,我正在经历并试图在一些错误处理中工作,但我不确定什么是最好的解决这个问题的方法是。

我被告知try-catch块可以是性能命中(在这种情况下这是一个大问题),是    这是真的 ?我应该谨慎地使用它们,或者只是在可以抛出异常的地方拍打它们    (我有点想在我所有的SQLite API调用中使用它们,因为我不知道到底是什么    他们做了一半的时间。)

使用事件回调对错误处理是一件坏事吗?建议我随时使用这些    可能,而不是try-catch,出于性能原因,但我不想打破任何设计    原则和范例,最终到处都是草率的代码。

第三种选择,它具有最少的开销,但是对于交易来说是极其恼人的    with,是status-fields和return values。

那你们觉得怎么样?我想我正在寻找一些大方向,也许还有一些关于何时何地使用每种方法的建议,以及我最有可能遗漏的任何其他技术。如果需要更多细节,请告诉我,因为我很乐意给他们。

感谢您抽出宝贵时间!

4 个答案:

答案 0 :(得分:4)

我认为让你的程序变得丑陋的是在任何地方进行异常处理,尽管事实上我们已经有了很好的异常处理模式。

这些将在您的代码库中发生的功能被称为Cross Cutting Concerns,如日志记录,安全性,审计,异常处理等....

您可以在http://msdn.microsoft.com/en-us/library/ee658105.aspx#ExceptionManagement找到好的模式。

值得一提的是,我不建议使用Microsoft文档中推荐的EntLib。

如果您寻找面向方面编程(AOP),您将找到很好的资源。 最后的提示是实现将使用依赖注入/ IoC框架来解决这些问题。

答案 1 :(得分:2)

  

我想在我所有的SQLite API调用中使用它们,因为我不知道他们在一半时间内做了什么。

如果您说使用库与SQLite进行交互,则此库API可能已经在某些错误情况下抛出异常。当然,在这种情况下,您应该在这些调用周围使用try / catch并处理这些错误情况。

如果您在使用其他人的图书馆时没有自己编写代码,情况总是如此。

您如何处理这些错误是您的决定。

我的建议:

  • 对于大多数情况,我反对回调/事件。当导致错误的API是异步的并且程序流程因此已经不是不言而喻时,这些应该主要用于。
  • 抛出异常确实比状态代码/返回值慢,但是在应用程序不是时间关键的任何情况下,它可以安全地在任何移动平台上使用。 手机游戏使用例外投掷,而且时间紧迫(有点)。
  • 抛出异常提供了更好的代码可读性 - 在我看来,这是一个主观的东西 - 并且是一种在出现错误时跳出当前上下文的好方法。

答案 2 :(得分:1)

如果希望捕获预期的异常,请使用try/catch。通常通过异常确定工作流程不是很好的选择,但在IO操作的情况下它可能是唯一的。例如,您写入一些突然失去连接的外部设备。在这种情况下,您的程序将获得异常,但必须像通常的错误一样处理它。

答案 3 :(得分:1)

有时候理论并不符合特定的实现,但我想Mono现在已经有了这些概念。

适当的运行时总是在无异常的情况下有利于性能。理想情况下,在没有抛出异常的情况下,try / catch块应该执行就像try块的内容自己执行一样,try / finally块应该像try和finally块的内容一样执行按顺序执行。当使用CIL字节码解释器时,通常不可能像我在这里提到的那样执行这些操作而没有开销。但是,一个像样的JIT或AOT编译器(就像你使用Mono一样)实际上产生的代码在无异常情况下运行速度与在省略try / catch / finally结构时一样快.¹

如果您选择错误代码策略,即使没有发生错误(将额外参数传递给方法,计算和测试返回代码等),您的应用程序也将最终执行错误处理代码的部分内容。因此,您的目标是将异常处理的使用限制在真正特殊情况下。这种策略可以实现强大的应用程序(正确的错误处理),而不会降低性能关键成功案例的性能。

¹在嵌入数值计算循环体中的try / finally块的情况下,这不是100%准确,但是当正确用于处理特殊情况时,它具有可观察到的性能影响的可能性几乎为零这点。具体而言,与没有try / finally块的相同方法相比,为X86编译的try / finally块JIT将包括类似于push / pop / jmp(本地分支)指令的代码。这比调用定义为public static void Foo() {}

的方法的开销要小