I was doing some .NET coding today and I ran into something I hadn't thought about before -- many of Microsoft's built-in methods for testing network connectivity (ping, TCP sockets, etc.) are very liberal about throwing exceptions if the connection fails.
Of course, in general cases it's not good to use exceptions in your program's control flow. I'm curious though -- if the .NET libraries so readily throw them, how can I avoid something like this (excuse possibly messy code, just throwing together an example):
bool TestConnection(string host)
{
bool connected;
Ping ping = new Ping();
PingReply reply = ping.Send(host);
connected = (reply.Status == IPStatus.Success);
return connected; // possibly won't return false because of exceptions
}
I could use a try-catch
开发者_开发知识库 block to handle the exception, but all I'd be doing is setting connected
to false. Isn't that basically swallowing the exception altogether since I'm discarding all the information from the exception? What's the best practice here?
you should surely catch the exception thrown by the .NET Framework and do not assume the only thing you can do is return false, depending on your application design and use case you may re-throw the exception and notify the upper layer that the network path entered does not exist anymore for example, or you return false and ignore the issue in other cases.
the .NET Framework is the ground we use to build things over and has to be generic, if you try to open a file which does not exists it throws FileNotFoundException then in some cases you create it and in some other cases you tell the user you could not find the file... it always depends on your own code and basic exceptions should be either avoided with defensive approaches or caught. :)
You should should avoid using Exceptions for control flow if possible. For example by using TryParse instead of Parse, checking for correct type or nonnullness instead of catching nullreference or typecaste exceptions.
But in this case you do not have another API available, so you must use the one which is available. Note that not catching exception in your TestConnection
would simply mean that the caller of your function has to do it, which would be the the bigger evil.
What are you using the connection for? You should use that class's methods instead of trying to pre-test it with Ping. Then, handle any connection failures as they are thrown.
in general cases it's not good to use exceptions in your program's control flow
Sometimes you will catch exceptions and use it for control flow. You just shouldn't do it when an architectural change or Try
-style method (e.g. int.TryParse
) exists, and you certainly should avoid it on any code path that has to be performant.
Sometimes you must do evil things. (Yes that is a C++ FAQ, but it a general programming rule).
Also - Don't catch Exception
, if you can possibly avoid it. Catch the specific derived exception type(s). If you write a catch block, you better be able to do the correct thing to handle that exception at that location, or rethrow with throw;
(not throw new ...
).
It depends on the method's purpose. For example, if you just want to get a bool to determine whether you can establish a connection, catch the exception and return false.
bool CanConnect(string host)
{
bool connected;
Ping ping = new Ping();
try
{
PingReply reply = ping.Send(host);
}
catch(/*catch the specific exception(s) here*/)
{
return false;
}
connected = (reply.Status == IPStatus.Success);
return connected; // possibly won't return false because of exceptions
}
But if you are wanting to test the connection and provide a more specific error as to why the connection failed, you would NOT want to catch the exception in this method. You would want to let the caller know exactly what went wrong by allowing the exception to bubble up.
This is consistent with Microsoft's guidelines for exception handling:
Do not overuse catch. Exceptions should often be allowed to propagate up the call stack. Catching exceptions that you cannot legitimately handle hides critical debugging information.
(From MS Exception Handling Guidelines)
This is not using an exception to manipulate control flow. This answer gives an example of using exceptions for control flow.
精彩评论