【问题标题】:How to test statements individually rather than a block of code using Try-Catch?如何使用 Try-Catch 单独测试语句而不是代码块?
【发布时间】:2014-06-03 15:02:06
【问题描述】:

下面的代码将失败,因为 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();
            }
        }

【问题讨论】:

  • 把它放到不同的方法中。
  • 不要破坏您自己的帖子,而是接受答案,发布您自己的答案(并接受它),或者将您的问题标记为版主删除。

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


【解决方案1】:

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

请注意,每个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();
        }
    }

【讨论】:

    【解决方案2】:

    如果异常总是被以同样的方式处理,你为什么不尝试这种方式......

    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();
        }
    }
    

    【讨论】:

      【解决方案3】:

      在这种情况下,我喜欢使用自定义包装类,我发现它们更简洁一些,并且更有能力根据您的需求进行自定义(尤其是在以更简洁的方式抛出错误时)

      所以你可以写一个实现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() 时,如果您尚未显式启动Shutdown(),它将启动给你)

      【讨论】:

        猜你喜欢
        • 2015-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-08
        • 1970-01-01
        相关资源
        最近更新 更多