what will empty catch and throw block do?

Optimization

The compiler will not optimize this out, even in a Release build.

Take the following test application:

public class Program {
    public static void Main(string[] args) {
        try {
            CallsThrow();
        }
        catch(Exception ex) {
            Console.WriteLine("Main() caught exception: " + ex.Message);
        }
        Console.Read();
    }

    private static void CallsThrow() {
        try {
            Throw();
        }
        catch {
            throw;
        }
    }

    private static void Throw() {
        throw new Exception("Here's my exception.");
    }
}

Using ILSpy we can look at the output binary at the IL level. We see that the try/catch in CallsThrow is still there in our Release binary:

.method private hidebysig static 
    void CallsThrow () cil managed 
{
    // Method begins at RVA 0x2094
    // Code size 11 (0xb)
    .maxstack 1

    .try
    {
        IL_0000: call void JunkCSharpConsole.Program::Throw()
        IL_0005: leave.s IL_000a
    } // end .try
    catch [mscorlib]System.Object
    {
        IL_0007: pop
        IL_0008: rethrow
    } // end handler

    IL_000a: ret
} // end of method Program::CallsThrow

Benchmark

Code:

public class Program
{
    public static void Main(string[] args) {
        const int N = 100000000;
#if DEBUG
        const string mode = "Debug";
#else
        const string mode = "Release";
#endif

        Console.WriteLine("Testing {0} iterations in {1} mode:", N, mode);

        // Attempt to JIT / cache
        CallsThrowWithTryCatch(false);
        CallsThrowWithoutTryCatch(false);

        // Test with try/catch+throw
        var s1 = Stopwatch.StartNew();
        for (int i = 0; i < N; i++ )
            CallsThrowWithTryCatch(false);
        s1.Stop();
        Console.WriteLine("  With try/catch: {0} ms", s1.ElapsedMilliseconds);

        // Test without try/catch+throw
        var s2 = Stopwatch.StartNew();
        for (int i = 0; i < N; i++)
            CallsThrowWithoutTryCatch(false);
        s2.Stop();
        Console.WriteLine("  Without try/catch: {0} ms", s2.ElapsedMilliseconds);

        var pct = (s1.ElapsedMilliseconds - s2.ElapsedMilliseconds) / (double)s1.ElapsedMilliseconds * 100.0;
        Console.WriteLine("No try/catch faster by {0:.02}%", pct);

        // Just show that it works
        try {
            CallsThrowWithTryCatch(true);
        }
        catch (Exception ex) {
            Console.WriteLine("Main() caught exception: " + ex.Message);
        }

        // Wait to exit
        Console.WriteLine("Press ENTER to exit.");
        Console.Read();
    }

    private static void CallsThrowWithTryCatch(bool doThrow) {
        try {
            Throw(doThrow);
        }
        catch {
            throw;
        }
    }

    private static void CallsThrowWithoutTryCatch(bool doThrow) {
        Throw(doThrow);
    }

    private static void Throw(bool doThrow) {
        if (doThrow)
            throw new Exception("Here's my exception.");
    }
}

Results:

Testing 100000000 iterations in Debug mode:
  With try/catch: 1492 ms
  Without try/catch: 1474 ms
No try/catch faster by 1.22%
Main() caught exception: Here's my exception.
Press ENTER to exit.

Testing 100000000 iterations in Release mode:
  With try/catch: 598 ms
  Without try/catch: 458 ms
No try/catch faster by 23.42%
Main() caught exception: Here's my exception.
Press ENTER to exit.

We can see that yes, there is a performance penalty associated with even the empty try/catch. In Debug builds it is not so significant, but a Release build showed a substantial 23.42% improvement by removing the try/catch.


Comments

  1. Caden

    • 2016/11/18

    I use empty catch blocks if necessary. Sometimes programmer of library I'm consuming doesn't know what he is doing and throws exceptions even in 

  2. Zander

    • 2017/6/18

    An empty catch block is fine in the right place - though from your sample I would say you should cetagorically NOT be using catch (Exception). You should instead catch the explicit exception that you expect to occur. The reason for this is that, if you swallow everything, you will swallow critical defects that you weren't expecting, too.

  3. Esteban

    • 2015/2/10

    This doesn't really leave any room for do-nothing, empty catch blocks. try { DoSomething(); //This should throw exception if everything works well 

  4. Malakhi

    • 2019/7/20

    Yes and No. Leaving the catch block completely empty catch ( Exception ) { } should be a hanging offence. Having an empty catch block that contains a meaningful, detailed comment about why it's OK to ignore this particular exception (and any sub-classes thereof) might be acceptable, but only in very limited circumstances. Re-throwing the same exception should only be done when you have a list of catch blocks and you need to "smuggle" a smaller Exception past the attention of a

  5. Orlando

    • 2019/12/6

    I know the following catch and throw block is redundant, I am curious what kind of damage it can do ? Can compiler optimizes it away in release mode?

  6. Houston

    • 2015/7/3

    I've read stern warnings about how an empty catch block is evil because it "swallows" the exception. Swallowing the exception is exactly what I want to do, here, actually, but the empty catch block still doesn't feel right, to me.

  7. Atticus

    • 2019/4/16

    Sometimes a piece of code throws a checked exception that you know can't occur. The catch block can still end up empty because you might also be using 

  8. Lance

    • 2018/6/26

    catch it, do something, but re-throw it for another layer to handle This doesn't really leave any room for do-nothing, empty catch blocks. EDITED TO ADD : suppose you are programming in a language where throwing exceptions is the normal way of controlling the program logic (one of alternatives to goto ).

  9. Emmett

    • 2015/10/21

    Yes, we can have an empty catch block. But this is a bad practice to implement in Java.Generally, the try block has the code which is 

  10. Ezequiel

    • 2015/12/28

    The Swift approach: try, catch, do and throw. If we wanted to load a file from a URL into a `Data` instance, we might write code like this: let contents: Data? do { contents = try Data(contentsOf: someURL) } catch { contents = nil } That illustrates three of the five new keywords you'll need to learn. The fourth and fifth keywords are throw and

  11. Robinson

    • 2018/7/20

    finally. A catch -block contains statements that specify what to do if an exception is thrown in the try -block. If 

  12. Sebastian

    • 2020/1/23

    Technically you can throw an exception (throw an error). The exception can be a JavaScript String , a Number , a Boolean or an Object : throw "Too big"; // throw a text

  13. Amari

    • 2015/5/10

    C# does not have checked exceptions so any empty catch block is normally a mistake or an instance of bad practice. Ignoring exceptions that should be dealt with 

  14. Elijah

    • 2015/1/12

    Yes u can use an empty catch block in your code. Usually empty try-catch is a bad idea because you are silently swallowing an error condition and then 

  15. Aiden

    • 2015/7/20

    An exception can be throw n, and caught (" catch ed") within PHP. Code may be surrounded in a try block, to facilitate the catching of potential exceptions.

  16. Jordy

    • 2017/4/18

    Ans) You can write a single catch block to handle all the exceptions thrown during the program. If you use the Superclass Exception in the catch block then 

Comments are closed.

Recent Posts