代码之家  ›  专栏  ›  技术社区  ›  Pretzel

还什么?Error String、Bool with Error String Out或Void with Exception

  •  2
  • Pretzel  · 技术社区  · 16 年前

    我把大部分时间花在C上,试图找出处理异常的最佳实践,并将错误消息从被调用方法干净地返回给调用方法。

    例如,下面是一些ActiveDirectory身份验证代码。 请将此方法想象为类的一部分 (不仅仅是一个独立的函数。)

    bool IsUserAuthenticated(string domain, string user, string pass, out errStr)
    {
      bool authentic = false;
      try
      {
        // Instantiate Directory Entry object
        DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass);
    
        // Force connection over network to authenticate
        object nativeObject = entry.NativeObject;
    
        // No exception thrown? We must be good, then.
        authentic = true;
      }
      catch (Exception e) { errStr = e.Message().ToString(); }
      return authentic;
    }
    

    这样做的好处是可以在If-Then-Else语句中嵌入明确的YES或NO。缺点是,它还需要使用该方法的人提供一个字符串来返回错误(如果有的话)

    我想我可以用相同的参数减去“out errStr”来重载这个方法,但是忽略这个错误似乎是个坏主意,因为这样的失败可能有很多原因。。。

    或者,我可以编写一个方法,返回一个错误字符串(而不是使用“out errStr”),其中返回的空字符串表示用户可以通过身份验证。

    string AuthenticateUser(string domain, string user, string pass)
    {
      string errStr = "";
      try
      {
        // Instantiate Directory Entry object
        DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass);
    
        // Force connection over network to authenticate
        object nativeObject = entry.NativeObject;
      }
      catch (Exception e) { errStr = e.Message().ToString(); }
      return errStr;
    }
    

    但这似乎是一种“软弱”的做事方式。

    或者我应该让我的方法为“void”而不处理异常以便将其传递回调用函数吗?

    void AuthenticateUser(string domain, string user, string pass)
    { 
       // Instantiate Directory Entry object
       DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass);
    
       // Force connection over network to authenticate
       object nativeObject = entry.NativeObject; 
    }
    

    这在我看来是最理智的(出于某种原因)。但同时,与在需要验证的任何地方键入这两行代码相比,将这两行代码包装起来的唯一真正优势是,我不需要包含“LDAP://”字符串。这种方法的缺点是,用户必须将此方法放入try-catch块中。

    思想?

    有没有其他我没想到的方法?

    3 回复  |  直到 16 年前
        1
  •  6
  •   Aaron Digulla    16 年前

    没有“一刀切”。如果您返回一个标志,那么在 if() 和循环。例外总是需要大量的锅炉板代码。如果您只需要一个可以显示给用户的字符串(例如,在web UI中),则返回错误字符串(或 null 因为“没有错误”)也是好的。

    但大多数时候,我抛出一个异常(在Java中是 RuntimeException )因为这允许我返回更多关于错误的信息(比如:哪个文件导致了错误?哪一行/哪一列?我在干什么?表单中的哪个字段应标记为非法?等等)。

    在您的例子中,您无法处理方法中的异常,因此不应该捕获它。只有当你能做点什么的时候才能抓住它。

        2
  •  3
  •   NerdFury    16 年前

    在这个例子中,我同意,您应该让异常流通过消费者。但是,作为你强调的方法的另一种选择,考虑这种方法。

    您可以使用响应对象来保存从方法运行中产生的信息,例如:

    public abstract class BaseResponse
    {
      public bool IsOk { get; protected set;}
      public string Message { get; protected set; }
    }
    
    public class AuthenticationResponse: BaseResponse
    {
      public AuthenticationResponse(bool isOk): this(isOk, "") {}
      public AuthenticationResponse(bool isOk, string message)
      {
        IsOk = isOk;
        Message = message;
      }
    }
    
    AuthenticationResponse IsUserAuthenticated(string domain, string user, string pass)
    {
      bool authentic = false;
      string errStr;
      try
      {
        // Instantiate Directory Entry object
        DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass);
    
        // Force connection over network to authenticate
        object nativeObject = entry.NativeObject;
    
        // No exception thrown? We must be good, then.
        authentic = true;
      }
      catch (Exception e) { errStr = e.Message().ToString(); }
      return new AuthenticationResponse(authentic, errStr);
    }
    

    然后在if语句中使用它:

    AuthenticationResponse response;
    if((response = IsUserAuthenticated("domain", "user", "pass")).IsOk)
    {
      // do successful activity
    } else {
      Console.WriteLine(response.Message)
    }
    

    诀窍是赋值操作的返回值就是被赋值的值。所以,我们可以在同一行中进行赋值和有效检查。如果不需要保留调用的结果,只需调用方法并检查IsOk属性即可。

    if(IsUserAuthenticated("domain", "user", "pass").IsOk)
    {
      // do successful activity
    }
    

    然后可以构建自定义响应对象,根据需要从方法返回任何值的组合。

        3
  •  2
  •   Gerrie Schenck    16 年前

    不要处理异常或返回任何类型的消息。让你的方法的使用者来处理这个问题。