正确的方法将错误传递回调用代码

时间:2014-05-20 11:25:16

标签: c# error-handling

我有一个名为connect的函数,如下所示:

public boolean connnect(){
{
 ..... connecting codde
 if(connectionSuccessfull)
 {
   return true;
 }
  else
 {
   return false;
 }
}

这是一种非常基本的错误处理形式,我想升级此函数以正确处理错误。比如告诉我 false 有错误,但可以说,错误,身份验证失败或超时错误等。 然后需要将此信息发送回调用者,以便知道发生了什么。

这样做的正确方法是什么?

{编辑} 在我看来,很可能会发生异常,我会说50%的时间。

我想出了这个,看起来部分正确吗?

namespace MobileWebServices.Exceptions
{
    //Timeout
public abstract class TimeOutException : Exception
{

}

public class ConnectingTimeOutException : TimeoutException
{
}

public class DissconnectingTimeOutException : TimeoutException
{

}

//Authetntication
public abstract class AuthenticationException : Exception
{

}
public class BadAuthenticationException : AuthenticationException
{

}
}

4 个答案:

答案 0 :(得分:2)

正常的方法是抛出异常(perhaps of a user-defined type),然后在更高级别捕获这些异常。

如果出于某种原因你不能使用异常,你可以编写一个包含错误消息的包装类(如果没有错误则为null)和bool结果(只有在错误消息为null)。

但是,我建议使用例外。 (唯一的问题可能是您是否需要在异常中全局化错误消息字符串,但是the consensus is that you should not。)

答案 1 :(得分:2)

有些事情:

public void Connect()
{
  try
  {
    //code here to look-up the connection details
    if(!ValidateConnectionDetails(details))
      throw new InvalidOperationException("The connection details are not valid.");
    //code here to establish the connection
    if(SomeTestThatShowsWereNotHappyWithTheConnection())
      throw new Exception("The connection is bad, for some reason");
  }
  catch(SocketException se)
  {
    //We'd only have this block if a socket exception is possible. We might just allow it to pass on up.
      throw; // User now gets the exception we got, exactly.
    //We might re-throw the error, but from here so the stack-trace goes to here rather than the innards of this method:
      throw se;
    //Most usefully we might throw a new exception that contains this as an inner exception:
      throw new Exception("Connecting failed", se);
    //Or even better, we might throw a more well-defined exception, that relates to this operation more specifically, with or without the inner exception, depending on whether that is likely to be useful:
      throw new ConnectionException("Some message, or maybe just a default is defined in the constructor");
    //OR:
      throw new ConnectionException("Some message, or maybe just a default is defined in the constructor", se);
  }
  catch(Exception ex)
  {
    //If we get to an exception ourselves that isn't of a particular type we're expecting, we probably shouldn't catch it at all. We might though want to note the exception before re-throwing it, or throw a more specific connection with this as an inner-exception:
    Log(ex);
    throw;
  }
}

由于您不再返回值来表示成功,因此您现在还可以返回表示您创建的连接的对象:

public ConnectionObject Connect()
{
   // Much as above, but returning the object before the end of the `try`.
}

只有在可能发生故障的情况下才会返回表示失败的值,并且您希望调用代码能够在调用时合理地做出反应。这不可能与代码连接,因为调用代码可能是代码,例如,代码。连接然后进行操作,而调用的代码又是应该捕获异常(无论是从这里还是后续操作)的地方 - 它是最终关心失败的代码。

在后一种情况下,返回表示失败的值会更有意义。在这里,我可能仍然会考虑一个异常,因为它可以封装更多信息,编码器以正常的方式使用其他.NET方法,并且因为调用代码可能不是书面思考"尝试获得连接,然后如果它工作..."它的书面思维"得到连接然后......"错误的情况就是这样;错误案例。 (为了进行比较,像int.TryParse()这样的方法是回答问题"这个字符串是否代表一个整数,如果是,它是什么?"方法int.Parse()回答了问题"这个字符串中的整数是多少?"没有整数是错误条件。)

以另一种方式来思考。您目前是否正在使用网络浏览器浏览网页,或者您是否正在使用它来尝试浏览网页?您的互联网连接可能会死于您,阻止您继续阅读这些答案,但您认为这是您尝试做的问题。

答案 2 :(得分:1)

以下是有关如何完成工作的示例:
首先使用connect()方法返回一个对象(例如Socket) 如果连接失败而没有抛出异常,则返回null 在你的connect()方法中,尝试/捕捉你的连接指令,并重新抛出那些被捕获的指示 然后在调用方法中,捕获所有可抛出的异常,并检查返回的对象是否为null。
以下是使用套接字的代码示例:

public static Socket connect()
{
    Socket s = null;
    try
    {
        IPEndPoint iEP = new IPEndPoint("127.0.0.1", 8080);
        s = new Socket(iEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        s.Connect(iEP);
        if(!s.Connected)
        {
            return null;
        }
    }
    catch(Exception e)
    {
        throw e;// Rethrow the Exception to the caller
    }
    return s;
}

public static void Main(String[] args)
{
    Socket mySocket = null;
    try
    {
        mySocket = connect();
    }
    catch(SocketException e)
    {
        // TODO - Detailed error about a SocketException
        Console.Error.WriteLine("SocketException: " + e.Message + "(" + e.ErrorCode + ")");
    }
    catch(SecurityException e)
    {
        // TODO - Detailed error about a SecurityException
        Console.Error.WriteLine("SecurityException: " + e.Message);
    }
    catch(Exception e)
    {
        // TODO - Detailed error about those Exceptions :
        // ArgumentNullException, ObjectDisposedException and InvalidOperationException
        Console.Error.WriteLine(e.GetType() + ": " + e.Message);
    }

    if(mySocket == null)
    {
        // TODO - Error while initializing the Socket
        Console.Error.WriteLine("Error while initializing the Socket");
    }

    // TODO - Use your Socket here
}

答案 3 :(得分:0)

我认为最好的方法是使用围绕您的调用的try catch异常,并使用您想要的异常:

catch(TimeoutException ex)
{
//Do something
}
catch(SqlException ex)
{
//do something
}

//....

catch(Exception ex)
{
//do something
}

确保捕获的顺序(最后的全局异常)