Правильный способ передачи ошибок обратно в вызывающий код

1

У меня есть функция, называемая connect вроде так:

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

Это очень простая форма обработки ошибок, я хочу обновить эту функцию, чтобы правильно обрабатывать ошибки. Например, не просто скажите мне, что ложь была ошибкой, но быть в состоянии сказать: ошибка, ошибка аутентификации или ошибка тайм-аута и т.д. Затем эту информацию нужно отправить обратно линии на вызывающего абонента, чтобы он мог знать, что произошло,

Каков правильный способ сделать это?

{EDIT} По моему мнению, вполне вероятно, что произойдет исключение, я бы сказал, что в 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
{

}
}
Теги:
error-handling

4 ответа

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

Обычный подход - это выброс исключения (возможно, определенного пользователем типа), а затем для исключения этих исключений на более высоком уровне.

Если по какой-то причине вы не можете использовать исключения, вместо этого вы можете написать класс-оболочку, включающий сообщение об ошибке (которое было бы нулевым, если бы не произошла ошибка) и результат bool (что было бы актуальным только в том случае, если сообщение об ошибке равно null).

Однако я бы рекомендовал использовать исключения. (Единственная проблема может заключаться в том, нужно ли вам глобализовать строку сообщения об ошибке в исключении, но консенсус в том, что вы не должны.)

  • 0
    О, хорошо, я вижу, так что я могу вернуть объект с именем Error, который я определяю. В каких случаях я бы не использовал исключения? Пробовать ловить не медленнее? Я могу ошибаться.
  • 1
    Это хорошо и часто, но вместо bool рассмотрите возможность использования int для статуса (0 для OK, rest для ERROR / FAILURE), поэтому вам не нужно анализировать строки, если вы хотите реагировать конкретно.
Показать ещё 5 комментариев
1

Вот пример того, как все должно быть сделано:
Сначала используйте метод connect() для возврата объекта (например, Socket).
Верните нулевой номер, если он не сможет подключиться, не выбрасывая исключение.
В вашем методе connect() попробуйте/поймайте свои инструкции по подключению и переверните их.
Затем в вызывающем методе поймайте все Исключения, которые могут быть выбраны, и проверьте, является ли возвращаемый объект нулевым или нет.
Вот пример кода с использованием Sockets:

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
}
  • 0
    Почему вы отбрасываете ? Разве этого недостаточно, чтобы вообще не использовать try / catch в connect() ?
  • 0
    Если у вас есть больше дел в блоке finally, например, закрытие соединения или освобождение ресурсов, отмена некоторых задач. Но по сути, перехват исключений в вызывающем методе - это главное.
Показать ещё 4 комментария
0

Я думаю, что лучший способ - использовать исключение catch catch, связанное с вашим вызовом, за исключением того, что вы хотите:

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

//....

catch(Exception ex)
{
//do something
}

Удостоверьтесь в порядке вашего улова (глобальное исключение в последнем)

  • 0
    Вот как использовать их метод, когда они знают, как правильно написать его в первую очередь.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню