Unreachable code, but reachable with an exception

前端 未结 9 1665
说谎
说谎 2020-12-28 11:22

This code is part of an application that reads from and writes to an ODBC connected database. It creates a record in the database and then checks if a record has been succes

相关标签:
9条回答
  • 2020-12-28 11:54

    You don't have a catch block, so the exception is still thrown, which blocks the return.

    the finally block would be executed, then would execute the return false; at the bottom.

    This is wrong, because the finally block would be executed, and then there would be an uncaught exception.

    finally blocks are used for cleanup, and they do not catch the exception. The exception is thrown before the return, therefore, the return will never be reached, because an exception is thrown before.

    Your IDE is correct that it will never be reached, because the exception will be thrown. Only catch blocks are able to catch exceptions.

    Reading from the documentation,

    Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement. Alternatively, you can catch the exception that might be thrown in the try block of a try-finally statement higher up the call stack. That is, you can catch the exception in the method that calls the method that contains the try-finally statement, or in the method that calls that method, or in any method in the call stack. If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation.

    This clearly shows that the finally is not intended to catch the exception, and you would have been correct if there had been an empty catch statement before the finally statement.

    0 讨论(0)
  • 2020-12-28 11:54

    When the exception is thrown, the stack will unwind (execution will move out of the function) without returning a value, and any catch block in the stack frames above the function will catch the exception instead.

    Hence, return false will never execute.

    Try manually throwing an exception to understand the control flow:

    try {
        command.CommandText = sb.ToString();
        returnValue = command.ExecuteNonQuery();
    
        // Try this.
        throw new Exception("See where this goes.");
    
        return returnValue == 1;
    } finally {
        command.Dispose();
    }
    
    0 讨论(0)
  • 2020-12-28 12:00

    It seems, you are looking for something like this:

    private static bool createRecord(string table,
                                     IDictionary<String,String> data,
                                     System.Data.IDbConnection conn,
                                     OdbcTransaction trans) {
      [... some other code ...]
    
      // Using: do not call Dispose() explicitly, but wrap IDisposable into using
      using (var command = ...) {
        try {
          // Normal flow:
          command.CommandText = sb.ToString();
    
          // True if and only if exactly one record affected
          return command.ExecuteNonQuery() == 1;
        }
        catch (DbException) {
          // Exceptional flow (all database exceptions)
          return false;
        }
      }
    }
    

    Please, note, that finally doesn't swallow any exception

    finally {
      // This code will be executed; the exception will be efficently re-thrown
    }
    
    // And this code will never be reached
    
    0 讨论(0)
提交回复
热议问题