Exception Handling (Legacy)

Note: Silver 8.1 originally an interim syntax for exception handling using non-standard keywords, described below. This syntax is being deprecated moving forward, if favor of the official do/catch syntax. Please see Exceptions and Error Handling for more details.

Silver extends the Swift language with support for exception handling on all platforms, simply because exception handling is a feature that cannot be avoided when working with the .NET or Java frameworks.

It introduces a few new keywords for this, namely __throw to raise an exception, and __try, __finally and __catch to handle them.

Throwing Exceptions

An exception can be thrown by using the __throw keyword followed by an exception instance, for example:

__throw ArgumentException("Parameter foo needs to be larger than 5")

When inside an exception handling block (more on that below), the __throw keyword can also be used on its own as a statement to re-throw the current exception.

Handling Exceptions

To protect code against exceptions, it can now be enclosed in a __try code block followed by a set of curly braces:

__try {
    println("This code is protected against exceptions.")
}

If an exception is encountered inside a __try block (including any code that the __try block calls out to), execution of that block is immediately terminated at that point.

How code execution will proceed will depend on the blocks following the __try. There are two ways react to exceptions:

Finally Blocks

__finally blocks can provide code that is guaranteed to be executed, regardless of wether an exception occurred or not. They are helpful for cleanup tasks – for example for closing file handles or disposing of other resources.

After the execution of the __finally block, any exception that had occurred will be re-thrown. In other words, the __finally block does not catch the exception.

__try {
    __throw Exception("Throwing a random exception here.")
    println("This code will never run.")
}
__finally {
    println("This code will always run.")
}
println("This code will also never run.")

Catch Blocks

__catch blocks can contain code that will only run if an exception is thrown. They are helpful for handling error conditions. By default, as the name implies, a __catch block catches the exception, handles it, and execution will continue after the block as if the exception never happened. The __throw keyword can be used to re-throw the exception, i.e. treat it as not caught and let it bubble up the call stack.

__try {
    __throw Exception("Throwing a random exception here.")
    println("This code will never run.")
}
__catch {
    println("This code will run only if an exception occurred above.")
}
println("This code will also run, because the exception was handled.")

Optionally, an exception type can be provided in order to only handle certain exceptions:

__try {
    __throw Exception("Throwing a random exception here.")
    println("This code will never run.")
}
__catch E: FileNotFoundExeption {
    println("Error \(E.Message) occurred")
}
println("This code may or may not run.")

Each __try block must be followed by at least one of the above two block types to react to the exception. Zero or one __finally can be present, depending one whether there is cleanup code that needs to run on now.

Any variable number of __catch blocks can be present, provided each of them catches a different exception type. If more than one __catch block is present, the first block that matches the concrete exception type will execute.

Only a single __catch block will ever be executed, even if multiple successive blocks would match the exception. This means that if you are looking to catch related exception classes using different __catch blocks, the blocks should be ordered with the most concrete class type first, and the most base class type (or possibly a type-less __catch block) last.