如何使用Try-Catch单独测试语句而不是代码块?

时间:2014-06-03 15:02:06

标签: c# try-catch try-catch-finally

下面的代码将失败,因为Bind()在尚未准备好的套接字上被调用",即使有代码准备套接字也是如此。准备套接字的代码超出了范围(另一个Try块)。

        // prepare socket
        try
        {
            socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        }
        catch (Exception e)
        {
            log.write("socket preparation failed");
        }
        finally
        {
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }

        // bind
        try
        {
            socket.Bind(endPoint);
        }   
        catch (Exception e)
        {
            log.write("Bind() failed");
        }
        finally
        {
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }

        // enable listening
        try
        {
            socket.Listen(1000);
        }
        catch (Exception e)
        {
            log.write("Listen() failed");
        }
        finally
        {
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }

3 个答案:

答案 0 :(得分:2)

这是编写它的一种方法。 finally是外部范围的一部分,而您的所有catches都在内部范围内。我在每个throwing之后catch,但您可以采用不同的方式处理它。

请注意,每个finally子句在其对应的try子句超出范围时执行,而不是在方法存在时执行。

    Socket socket;

    try
    {
        // prepare socket
        try
        {
            socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        }
        catch
        {
            log.write("socket preparation failed");
            throw;
        }

        // bind
        try
        {
            socket.Bind(endPoint);
        }   
        catch
        {
            log.write("Bind() failed");
            throw;
        }

        // enable listening
        try
        {
            socket.Listen(1000);
        }
        catch
        {
            log.write("Listen() failed");
            throw;
        }
    }
    finally
    {
        if (socket != null)
        {
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
        }
    }

答案 1 :(得分:0)

如果异常总是以同样的方式对待,为什么不尝试这种方式......

string message = string.Empty;

try
{
    message = "socket preparation failed";
    socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

    message = "Bind() failed";
    socket.Bind(endPoint);

    message = "Listen() failed";
    socket.Listen(1000);

    message = string.Empty;
}
catch
{
    log.write(message);
}
finally
{
    if (socket != null)
    {
        socket.Shutdown(SocketShutdown.Both);
        socket.Close();
    }
}

答案 2 :(得分:0)

在这种情况下,我喜欢使用自定义包装器类,我发现它们更整洁,并且能够根据您的需求进行自定义(特别是在以整洁的方式抛出错误时)

所以你可以编写一个实现Socket的类,我们称之为CustomSocket

public class CustomSocket : Socket {

    private EndPoint endPoint;

    public CustomSocket(EndPoint endPoint, SocketType socketType, ProtocolType protocolType)
        : base(endPoint.AddressFamily, socketType, protocolType) {
            this.endPoint = endPoint;
    }

    public virtual void Bind() {
        try {
            base.Bind(endPoint);
        } catch {
            // do logging here
            throw new Exception("Bind() failed");
        }
    }

    public virtual void Listen(int backlog) {
        try {
            base.Listen(backlog);
        } catch {
            // do logging here
            throw new Exception("Listen() failed");
        }
    }

    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected override void Dispose(bool disposing) {
        base.Dispose(disposing);
    }
}

然后你可以这样实现它:

        using (CustomSocket socket = new CustomSocket(new IPEndPoint(new IPAddress(new byte[1]), 5000), SocketType.Stream, ProtocolType.Tcp)) {
            try {
                socket.Bind();
                socket.Listen(1000);
            } catch (Exception ex) {
                // do stuff with ex here
            }
        }

此外,实施此using方法会使您不必手动拨打Close()和/或Shutdown()。 (using在结束时自动调用Dispose(),而Dispose()Close()相同。调用Close()时,如果您没有{39} ; t已经明确发起了Shutdown()它会为你启动它)