У меня есть функция, называемая 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
{
}
}
Что-то вроде:
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()
отвечает на вопрос "что такое целое число в эту строку? ", где не было целого числа, являющегося условием ошибки).
Подумать об этом по-другому. Вы используете веб-браузер для просмотра веб-страниц или используете его, чтобы попытаться просмотреть веб-страницы? Ваше интернет-соединение может умереть на вас, не позволяя вам продолжать читать эти ответы, но вы бы подумали, что проблема в том, что вы пытались сделать.
Обычный подход - это выброс исключения (возможно, определенного пользователем типа), а затем для исключения этих исключений на более высоком уровне.
Если по какой-то причине вы не можете использовать исключения, вместо этого вы можете написать класс-оболочку, включающий сообщение об ошибке (которое было бы нулевым, если бы не произошла ошибка) и результат bool
(что было бы актуальным только в том случае, если сообщение об ошибке равно null).
Однако я бы рекомендовал использовать исключения. (Единственная проблема может заключаться в том, нужно ли вам глобализовать строку сообщения об ошибке в исключении, но консенсус в том, что вы не должны.)
Вот пример того, как все должно быть сделано:
Сначала используйте метод 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
}
try
/ catch
в connect()
?
Я думаю, что лучший способ - использовать исключение catch catch, связанное с вашим вызовом, за исключением того, что вы хотите:
catch(TimeoutException ex)
{
//Do something
}
catch(SqlException ex)
{
//do something
}
//....
catch(Exception ex)
{
//do something
}
Удостоверьтесь в порядке вашего улова (глобальное исключение в последнем)