在c#中捕获异常时要返回什么

Ram*_*ing 3 c#

这可能是一个非常简单的问题,但是try-catch块上的返回类型的最佳实践是什么?目前,我正在做这样的事情:

 public List<SomeAttribute> FindAttributes(int id)
   {
       try
       {
            //Some query and some logic
       }
       catch (Exception ex)
       {
           Logger.Error(ex);
           return new List<SomeAttribute>();
       }
   }
Run Code Online (Sandbox Code Playgroud)

这有什么特别可怕的吗?异常将被记录,该方法将返回一个空列表 - 调用函数可以处理.返回null更好吗?如果是这样的话?

Wil*_*sem 6

通常,我们会考虑三种处理部分函数的策略(只有输入域的子集有效的函数):Total,DefensiveNominal.

这意味着你总是回答一个答案.在这种情况下,您可以考虑返回null-pointer,String.IndexOf例如返回一个-1.

好处:

  • 有时呼叫者不会考虑潜在的错误.有时返回值可能很有用.例如,如果你想切断字符串的第一部分(包括第一个逗号),你可以将其编码为:

    string foo = "Foo,Bar"
    string foocut = foo.SubString(foo.IndexOf(',')+1); //Bar, in case no comma, it returns the entire string
    
    Run Code Online (Sandbox Code Playgroud)

    从而产生更紧凑的代码.但另一方面,有时很难确定最佳回报值是多少.

缺点:

  • 它需要工程来确定" 最佳 "返回值.有很多选项,每个选项只对部分呼叫者有益.
  • 有时候无法区分出现错误的有效输出和出现问题时的(默认)输出.

防御性

在这里抛出异常(或者不捕获异常).由特定于域的调用者决定为什么抛出异常并准确处理.Util方法通常对系统知之甚少,因此不知道异常发生的原因.

好处:

  • 具有最佳知识的调用者可以处理该异常(因此某种" 责任链 ").这可以导致更好的错误处理(向用户提供有用的消息).不是" 发生了错误的SQL查询...... ",而是" 用户名已经存在. "

缺点:

  • 错误处理有时很难.特别是在C#中,其中一个不需要注释方法可以抛出哪个异常.要涵盖所有类型的例外情况并不容易.未捕获的异常可能会返回到顶层Main调用崩溃应用程序.对于像Web服务器这样的应用程序,这并不总是一种选择.

公称

在这里,您将记录您的方法并提供预先编码:在文档中,您指定了使用该方法的正确方法.这并不总是可行的,因为有时方法成功的事实取决于外部因素(服务器的可用性,OS的类型,......).程序员不一定控制的因素.

好处:

  • 结果记录良好(有时是严格的)定义方法.
  • 实现方法(被调用者)更容易,因为它可以假设一切都会正常工作.

缺点:

  • 并非总是可能(有时结果取决于人们无法控制的因素).
  • 编写调用者更难,因为它有一个契约,它只会使用正确的参数调用该方法.
  • 记录所有条件以及验证每个调用是否满足它们也很困难.有时代码契约用于自动处理验证(部分).

大多数计划并不坚持使用一种策略,而是将它们混合使用:例如,一些例外处理总计,其他例外处理,其他处于防御状态.或者一些模块遵循防御策略,而另一个模块使用名义编程.