[Mono-list] Exceptions and error codes.

Piers Haken piersh@friskit.com
Thu, 20 Mar 2003 12:59:19 -0800


> -----Original Message-----
> From: Thong Nguyen [mailto:tum@veridicus.com]=20
> Sent: Thursday, March 20, 2003 12:14 PM
> To: mono-list@lists.ximian.com
> Subject: [Mono-list] Exceptions and error codes.
>=20
>=20
> Hiya guys,
>=20
> I recently read some recommendations on the GTK# mailing list=20
> regarding the use of exceptions.

You make some good arguments, but I think most of it is irrelevant
since, in order to remain compatible with .NET, Mono must behave the
same way with respect to returning (or not) exceptions. The MSDN docs
describe exactly what exceptions/return codes File.Exists and File.Open
should return, Mono should do the same (unless the docs are in error). A
lot of work has already been done on this. You'll notice that many of
the test cases test whether or not the correct exception is being
returned.

Of course, for new class libraries many of your arguments are valid.
Although I'd argue that the case for exceptions in .NET isn't as
clear-cut as you propose.

For example, since you're not required to declare the exceptions that a
method throws, it's just as easy to miss handling an exception as it is
to miss handling a return code. The argument that it's easy to forget to
handle a return code is purely subjective. I've been writing COM code in
C++ since '95 and I've found that it's quite simple to get into the
habit of checking the result of every call and doing it in a way that's
readable. In fact I often find that code that explicitly checks return
codes for each call is easier to read than code that relies on catch
blocks, since you know exactly which error handling code is associated
with each call. Catch locks are fine if you want to apply the same
exception handling code to a whole bunch of code, but as soon as you
have to nest them they become unwieldy.

For example, compare:

try
{
	DoSomething ();
	try
	{
		DoSomethingElse ();
		// some more code here...
	}
	catch (Exception e)
	{
		// handle exception in DoSomething ()
	}
}
Catch (Exception e)
{
	// handle exception in DoSomethingElse ()
}

With

HRESULT hr;
if (FAILED (hr =3D DoSomething ()))
{
	// handle error in DoSomething ()
}
else if (FAILED (hr =3D DoSomethingElse ()))
{
	// handle error in DoSomethingElse ()
}
else
{
	// some more code here...
}



Or, if you don't need nested catch blocks:


HRESULT hr;
if (FAILED (hr =3D DoSomething ()) ||
    FAILED (hr =3D DoSomethingElse ()))
{
	// handle error
}
else
{
	// some more code here...
}

Or, if you prefer your error handling to be at the end:

HRESULT hr;
if (SUCCEEDED (hr =3D DoSomething ()) &&
    SUCCEEDED (hr =3D DoSomethingElse ()))
{
	// some more code here...
}
else
{
	// handle error
}

Piers.