On Saturday, 10 October 2020 at 18:16:45 UTC, Ali Çehreli wrote:
On 10/10/20 9:16 AM, DMon wrote:
> catch (Exception e) // implicit (any exception)
> catch (ConvException f) // explicit (conversion only)
>
> Or is that not correct?
I think in class hierarchies, "more general" and "more
specific" are better terms. :)
The answer is, catch by the most general under the Exception
hierarchy that you care about. It depends on the program. In
most of my programs, catching Exception in main is sufficient
because I just print the error message.
However, sometimes the error message does not make sense at
that level:
So, you can augment that error with another one:
One cool thing about storing the 'actual' exception is, you can
later debug it by catching the specific FooException and
printing 'actual' as is, which contains the stack trace:
But really, it all depends on your program. The simplest thing
may to not catch at all. The default behavior is to dump the
stack trace and it works for some programs.
Ali
I will copy that down.
The idea for specific exceptions came from the online docs and
Programing in D, 39.2 The try-catch statemet
try
{ // the code block that is being executed, where an // exception
may be thrown
}
catch (an_exception_type)
{ // expressions to execute if an exception of this // type is
caught
}
catch (another_exception_type)
{ // expressions to execute if an exception of this // other type
is caught // ... more catch blocks as appropriate ...
}
finally
{ // expressions to execute regardless of whether an // exception
is thrown
}
This is where I'm at:
import std.stdio;
import std.conv;
// StdioException
// ConvException
// StringException
// ErrnoException
// FormatException
// UnicodeException
// UTFException
// FileMissingException
// DataCorruptionException
// FE_INEXACT
// FE_UNDERFLOW
// FE_OVERFLOW
//
int main()
{
string z1 = "+ "; string z2 = "++ ";
bool a1 = false; bool a2 = true;
int b1 = 0; int b2 = 1;
uint c1 = 0; uint c2 = 1;
float d1 = 1f; float d2 = 2f;
char e1 = 'a'; char e2 = 'b';
int o1; int o2;
// auto test;
int[3] ar1; int[5] ar2;
string st1 = "arg";
writeln("Control\n\n");
/*
writeln("Testing");
try
{
writeln(z1 ~ e1 ~ st1);
writeln();
}
catch (Exception y1)
{
writeln("Something ", y1.msg,
y1.info);
}
*/
writeln("try...catch");
try
{
o1 = to!int("hello");
}
catch (Exception i1)
{
writefln(z1 ~ "Message from exception i1: %s", i1.msg);
writefln(z1 ~ "Info from exception i1: %s", i1.info);
}
writeln();
writeln("try...finally");
try // Will run as normal code.
{
o1 = a2 + b2;
writeln(z1 ~ "", o1);
}
finally
{
writeln("Continues to run normally and no exceptions are
displayed.");
}
writeln();
writeln("try...catch...finally");
try
{
to!int(z1);
to!int(z2);
}
catch (ConvException j1)
{
writefln(z1 ~ "1st Exception msg: %s", j1.msg);
writeln();
}
catch (Exception k1)
{
writeln(z1 ~ "2nd Exception msg: %s", k1.msg);
}
finally
{
writeln(z1 ~ "There are two exceptions.");
writeln(z2 ~ "The first exception is caught and that,
immediately, exits the try clause.");
}
writeln("This still runs.");
writeln();
/*
writeln("Nesting");
try
{
*/
return 0;
}