C# Exception is Unchecked???

  • Thread starter Thread starter ChInKPoInt [No MCSD]
  • Start date Start date
C

ChInKPoInt [No MCSD]

I am using Visual Studio 2K3 writing a ASP.NET web application. Is there a
way to force the C# compiler to catch possible exception?

In Java, all exceptions thrown MUST BE caught, otherwise compiler would give
you error. In C#, is there a way to do that?
 
now you know why I don't use Java.

No, C# will not FORCE you to catch your errors. That's up to you to do, and
it makes sense. You don't always want to catch every error locally. While
it is good practice, it should not be an absolute requirement.

--- Nick
 
Nick Malik said:
now you know why I don't use Java.

No, C# will not FORCE you to catch your errors. That's up to you to do, and
it makes sense. You don't always want to catch every error locally. While
it is good practice, it should not be an absolute requirement.

It's not in Java. You don't have to catch every exception (or even
checked exception) locally - you just have to declare which checked
exceptions you can throw.

I believe that checked exceptions of some kind are a good idea; I'm not
sure that Java got it right, and C#/.NET didn't get it right by getting
rid of them entirely. Java feels slightly cumbersome because of them,
and C# sometimes feels like driving without a seatbelt due to the lack
of them. The first language/platform which gets exception handling
really "right" will be interesting...
 
Nope C# doesn't support checked exceptions. Heres a transcript of Bruce Eckle and Anders Hejlsberg discussing why they are not in C#.

http://www.artima.com/intv/handcuffs.html

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

I am using Visual Studio 2K3 writing a ASP.NET web application. Is there a
way to force the C# compiler to catch possible exception?

In Java, all exceptions thrown MUST BE caught, otherwise compiler would give
you error. In C#, is there a way to do that?
 
Richard Blewett said:
Nope C# doesn't support checked exceptions. Heres a transcript of Bruce
Eckle and Anders Hejlsberg discussing why they are not in C#.

http://www.artima.com/intv/handcuffs.html

I find the "versioning" argument here weak, for two reasons:

The implication is that a method

void M() throws A, B, C

throws precisely A, B and C, and that this handcuffs you in reimplementing
the method. In fact, the method can be changed to throw any subclass of A,
B or C without breaking compatibility. If you're designing a method that
has to remain compatible (one in a widely used library, like the .NET
Framework) A, B and C should be categories of exception like IOException,
not the specific IO exceptions that can be thrown in the first
implementation.

One advantage of checked exceptions is that it allows the documentation to
know which exceptions are thrown. Compare the JDK Javadoc with the .NET API
documentation. You'll see how much better the Javadoc is about showing
which exceptions are thrown and why.
 
Mike Schilling said:
I find the "versioning" argument here weak, for two reasons:

The implication is that a method

void M() throws A, B, C

throws precisely A, B and C, and that this handcuffs you in reimplementing
the method. In fact, the method can be changed to throw any subclass of
A, B or C without breaking compatibility. If you're designing a method
that has to remain compatible (one in a widely used library, like the .NET
Framework) A, B and C should be categories of exception like IOException,
not the specific IO exceptions that can be thrown in the first
implementation.

How much does it really help you to know that the method throws some kind of
IOException without telling you which ones?

Also, for versioning, consider the case where a method had previously been
written to handle FileStream I/O and therefore had a throws IOException but
now wants to be able to get data from a network as well. The FileStream
parameter is changed to Stream, and the throws clause is changed to include
NetworkException, and you've got a versioning problem.
One advantage of checked exceptions is that it allows the documentation to
know which exceptions are thrown. Compare the JDK Javadoc with the .NET
API documentation. You'll see how much better the Javadoc is about
showing which exceptions are thrown and why.

Should ease of automatic documentation be a reason to implement a language
feature like this? An <exception> tag in Xml comments in C# solves this
problem without constraining the language.

John Saunders
 
I believe that checked exceptions of some kind are a good idea; I'm not
sure that Java got it right, and C#/.NET didn't get it right by getting
rid of them entirely. Java feels slightly cumbersome because of them,
and C# sometimes feels like driving without a seatbelt due to the lack
of them. The first language/platform which gets exception handling
really "right" will be interesting...

Yet...somehow I think you'll still find a large percentage of people who
like the java or C# way...

I wonder what right is.
 
John Saunders said:
How much does it really help you to know that the method throws some kind
of IOException without telling you which ones?

Quite a bit.

public void close() throw IOException;

Java reminds you that a close does I/O that can fail (in particular buffer
flushing.) C# doesn't. Any guesses how much C# code handles failures in
Close() ?
Also, for versioning, consider the case where a method had previously been
written to handle FileStream I/O and therefore had a throws IOException
but now wants to be able to get data from a network as well. The
FileStream parameter is changed to Stream, and the throws clause is
changed to include NetworkException, and you've got a versioning problem.

Not when Network exception is a subclass of IOException, which logically it
will be.
Should ease of automatic documentation be a reason to implement a language
feature like this? An <exception> tag in Xml comments in C# solves this
problem without constraining the language.
But the exception tags don't get put in C# methods, they do get put into the
Java ones.
 
Mike Schilling said:
Quite a bit.

public void close() throw IOException;

Java reminds you that a close does I/O that can fail (in particular buffer
flushing.) C# doesn't. Any guesses how much C# code handles failures in
Close() ?

All of mine does. ;-)

Look, _anything_ can fail. It does you little good to know that Close() can
throw IOException. How much does that help you over "throws Exception"?
Not when Network exception is a subclass of IOException, which logically
it will be.

Why? It isn't in .NET. Don't know about the Java case. If network exceptions
are subclasses of IOException, then tell me what is _not_ a subclass of
IOException (aside from Exception).
But the exception tags don't get put in C# methods, they do get put into
the Java ones.

The exception tags get put in by developers who want to document what
exceptions are thrown, and it didn't take a language feature to get that
done. And they're likely to be a lot more specific that "IOException".

John Saunders
 
John Saunders said:
All of mine does. ;-)

Good for you. Mine too. A lot doesn't, just in as C, a lot didn't check
the return status from close() or fclose().
Why? It isn't in .NET. Don't know about the Java case. If network
exceptions are subclasses of IOException, then tell me what is _not_ a
subclass of IOException (aside from Exception).


Illegal argument?
Invalid state?
Concurrent modification?
No such class/method/field?
Access not allowed?
etc.

The exception tags get put in by developers who want to document what
exceptions are thrown, and it didn't take a language feature to get that
done. And they're likely to be a lot more specific that "IOException".

Then why is the .NET framework documentation so poor in documenting
exceptions compared to the JDK docs?
 
Mike Schilling said:
Good for you. Mine too. A lot doesn't, just in as C, a lot didn't check
the return status from close() or fclose().



Illegal argument?
Invalid state?
Concurrent modification?
No such class/method/field?
Access not allowed?
etc.



Then why is the .NET framework documentation so poor in documenting
exceptions compared to the JDK docs?

The JDK docs naturally document what's in the throws clauses. I'm not even
sure whether the .NET documentation comes from Xml comments in C# code.

John Saunders
 
Really, I wasn't going to comment on this holy-war, but I think I will
anyway.

INTRO
-----

Checked exceptions seems like a good idea at first, which is probably
why it's included in JAVA. Unfortunatly it has a few problems, owing
sub-typing and the variance of errors, which makes it tempting to
declare every method "throws Throwable". I will shortly discuss the
problem with current implementations of checked exceptions and then
propose a method which makes checked exceptions beneficial in the way
checked-exception proponents usually argue it is.

EXAMPLE
-------

Let's do an example, C# syntax (this is m*.p*.d*.l*.csharp :) with
checked exceptions as in Java.

/** Persist objects, allow retrieval by id */
interface ObjectStore {
int Store(Object);
Object Retrieve(int id);
}

Now for a specific implementation that uses a directory with files for
storage:
public class DiskObjectStore: ObjectStore {
string Directory;
Object Retrieve(int id) {
using ( Stream s =
File.Open(File.Combine(Directory, id.ToString()))) {
// fetch object
...
}
}
}

WHAT SHOULD WE DO WITH THE D***** EXCEPTION
-------------------------------------------
(chorus: WITH THE D***** EXCEPTION)

Obviously File.Open(...) can throw a FileNotFound exception, so should
we catch and discard that? probably not, since we would deprive the
caller of accurate information about what failed.

So, we have to change the declaration of Retrieve:

Object Retrieve(int id): throws FileNotFound {...}

But that doesn't match the interface, and the interface declaration has
to be expanded to include a "throws FileNotFound". This removes the
abstractness of the interface, so you might suggest: "every
implementation of ObjectStore must do some I/O, so we'll let it throw
IOException".

Cutting heels and clipping toes
-------------------------------

This ensnaring argument hides the fundamental problem: you declared the
interface to be implementation-independant in the first place. Even
worse many implementations might NEVER throw an IOException, for example
a test-implementation:

public class MemoryStorage: ObjectStore {
IDictionary objects = new HashTable();
Object Retrieve(int id) throws IOException {
return objects[id]; // cannot throw IOException
}
}

or they might throw a whole new type of exception:

int id_count = 0;
int Store(Object o) {
int id = ++id_count; // ignore concurrency problems for now, ok?
if ( id_count == 0 )
throw new OutOfNamespace(o);
else
objects[id] = o;
}

When it's NOT a feary-tale
--------------------------

In the real world, what you end up with is usually either a global
throws declaration in the interface (and on all the callers of the
interface methods):

Object Retrieve(int id): throws Exception();

Or (nervous ticks starts) every implementation doing:

try {
using ( Stream s =
File.Open(File.Combine(Directory, id.ToString()))) {
// fetch object
...
}
} catch ( Exception e ) {
// an error occured, lot's of info in e, let's throw it away
return null;
}

And a VERY confusing code-style (*mildly* better: Logging errors and
returning null's.)

This is what most JAVA programmers do, atleast in the code i've seen :)

Wrapping extinguish type
------------------------

The last (and worst) alternative (which unfortunatly is done in a lot of
places in .NET) is to wrap the exception:

try {
using ( Stream s =
File.Open(File.Combine(Directory, id.ToString()))) {
// fetch object
...
}
} catch ( Exception e ) {
throw new ObjectStoreException(e);
}

This prevents the caller from even catching on the actual type of
exception occuring, and thus robs him of a viable retry strategy (unless
he wants to traverse the .Inner's of exceptions looking for the real
problem. This would take HEAPS of code, especially if more than one
wrapping is done). It actually removes the whole point of having Types
exceptions :)

*** NOTE: .NET Delegate's do exception wrapping, making catch on a
delegate-invocation a VERY delicate thing to try.

So, while checked exceptions have some nice properties, they really are
tedious to work with when polymorphism is used, since they precisely
expose the implementation differences that you wished to ignore by using
polymorphism.

JAVA
----

Now, zooming in on JAVA: JAVA has excepted that having every exception
as checked is too tedious. In JAVA there are RuntimeException's that may
be thrown *without* declaration in throws statements, and we may even
declare such an exception ourselves, BUT the class heirarchy is used to
indicate whether an exception should be checked or not.

This is higly unfortunate, since it deprives the programmer of the
ability to decide seperatly from situation to situation how "important"
a specific type of exception is, whether it should be catched or not by
the caller.

PROPOSAL
--------

If it was possible to declare "throws" statements on functions and
require callers to either handle or declare the exceptions themselves
(no class-hierarchy spec. of what should be checked here), AND it was
possible to "uncheck" an exception, allowing the caller to knowingly
pass a previously checked exception from a function as unchecked, now
that WOULD be usefull.

It would allow us to write the interface from above in the way we
wanted, without any throws qualifier, but it would allow File.Open to
declare that a FileNotFoundException could reasonably occur and that the
caller should do something about it.

The resulting code would be something like (with a newly invented syntax
for "unchecking", could probably be MUCH ):

using ( Stream s =
uncheck(File.Open(File.Combine(Directory, id.ToString()))),
FileNotFound)
{
// fetch object
...
}

The "uncheck" generates no code, and no catch-handler, it simply
instructs the compiler that the programmer knows that the call to
File.Open may cause an exception, but that should be accepted at
runtime, rather the provably handled by the caller.

CONCLUSION
----------

In this way the intrusion of checked exceptions may be kept to a
tolerable level, and cheked exceptions declarations can be actually
utilized to indicate "hey mate, this might fail, and you better have
something up your sleeve if it does".
 
Helge Jensen said:
Really, I wasn't going to comment on this holy-war, but I think I will
anyway.

Thanks for the comment, and thanks for bringing it out of .aspnet. I'll keep
it in the list for a while, for anyone following this there, but if this
goes on for long, I hope we can all agree that .aspnet time is over. :-)

....
*** NOTE: .NET Delegate's do exception wrapping, making catch on a
delegate-invocation a VERY delicate thing to try.

I was unaware of this. Could you provide some detail on this behavior?
PROPOSAL
--------

If it was possible to declare "throws" statements on functions and require
callers to either handle or declare the exceptions themselves (no
class-hierarchy spec. of what should be checked here), AND it was possible
to "uncheck" an exception, allowing the caller to knowingly pass a
previously checked exception from a function as unchecked, now that WOULD
be usefull.

It would allow us to write the interface from above in the way we wanted,
without any throws qualifier, but it would allow File.Open to declare that
a FileNotFoundException could reasonably occur and that the caller should
do something about it.

I have some question in general about this entire area. The fact is that,
when my code can handle an exception, I handle it. But when it doesn't have
anything useful to contribute to the processing of the exception, I get out
of the way and let my callers deal with it. Maybe the caller can handle the
exception, even though there's nothing useful I can do with it right now.

I _do_ sometimes wrap exceptions with something more application-specific.
For instance, I have a Login method for logging in to a web service. This
method will wrap a SoapException in a LoginFailedException. Presumably, my
caller called me in order to log in, and should be told that the login
failed. My Message says, "Can't log in as <username>", which is more useful
than "required header not supplied in call". If my caller thinks he knows
what to do about a SoapException, I supply it to him as the InnerException
property, but I don't decline to give him useful information on the off
chance that he really wanted to see that SoapException instead of my
LoginFailedException.

I assume that my callers are taking care of their IDisposable resources with
"using" blocks or the equivalent. I assume they're backing out of anything
else that needs backing out of with "finally" blocks. And I assume they have
a strategy for what to do with exceptions that nobody has been able to
handle. Maybe they've got a try-catch block around their message loop, or,
perhaps they do like I often do in Windows Forms applications, and place
their entire event handler in a try-catch block. Maybe my ultimate caller is
an ASP.NET application which handles all unhandled exceptions in Global.asax
and needs to e-mail exception details to the support group and write them to
the Windows event log?

In any case, none of those questions should have anything to do with me as a
class library designer. I should handle the exceptions if I can do so
usefully, I should wrap the exceptions if I want to make them more relevant
to my direct caller, and otherwise, I should stay out of the way!

And, BTW, I should document what exceptions I throw so that my callers can
think about their exception handling strategies ahead of time. In my
documentation, I should not only indicate which exceptions I throw (which is
what a "throws" clause does in Java), but I should also indicate _why_ the
exception might be thrown and perhaps give guidance as to what a caller
might do about it:

John Saunders
 
Helge Jensen said:
Really, I wasn't going to comment on this holy-war, but I think I will
anyway.

INTRO
-----

Checked exceptions seems like a good idea at first, which is probably why
it's included in JAVA. Unfortunatly it has a few problems, owing
sub-typing and the variance of errors, which makes it tempting to declare
every method "throws Throwable". I will shortly discuss the problem with
current implementations of checked exceptions and then propose a method
which makes checked exceptions beneficial in the way checked-exception
proponents usually argue it is.

EXAMPLE
-------

Let's do an example, C# syntax (this is m*.p*.d*.l*.csharp :) with checked
exceptions as in Java.

/** Persist objects, allow retrieval by id */
interface ObjectStore {
int Store(Object);
Object Retrieve(int id);
}

No exceptions defined at this level? These methods can never fail?

Let's start by thinking about how Retrieve, for example, can fail.

1. The id can fail to refer.
2. The object store in use was never initialized.
3. An error occurred fetching (e.g. deserializing) this object.

That's not exhaustive, but it's a start.

Thus:

public Object Retrieve(int id) throws NoSuchObjectException,
StoreNotInitializedException, RetrieveFailedException
Now for a specific implementation that uses a directory with files for
storage:
public class DiskObjectStore: ObjectStore {
string Directory;
Object Retrieve(int id) {
using ( Stream s =
File.Open(File.Combine(Directory, id.ToString()))) {
// fetch object
...
}
}
}

WHAT SHOULD WE DO WITH THE D***** EXCEPTION

Is this supposed to be hard?

catch(IOException ex)
{
throw new NoSuchObjectException("" + id + " is not a valid object
identifier", ex);
}
 
Thanks for all your comments. Helge comments and Richard's link are very
helpful.

C.P. [No MCSD]


Helge Jensen said:
Really, I wasn't going to comment on this holy-war, but I think I will
anyway.

INTRO
-----

Checked exceptions seems like a good idea at first, which is probably
why it's included in JAVA. Unfortunatly it has a few problems, owing
sub-typing and the variance of errors, which makes it tempting to
declare every method "throws Throwable". I will shortly discuss the
problem with current implementations of checked exceptions and then
propose a method which makes checked exceptions beneficial in the way
checked-exception proponents usually argue it is.

EXAMPLE
-------

Let's do an example, C# syntax (this is m*.p*.d*.l*.csharp :) with
checked exceptions as in Java.

/** Persist objects, allow retrieval by id */
interface ObjectStore {
int Store(Object);
Object Retrieve(int id);
}

Now for a specific implementation that uses a directory with files for
storage:
public class DiskObjectStore: ObjectStore {
string Directory;
Object Retrieve(int id) {
using ( Stream s =
File.Open(File.Combine(Directory, id.ToString()))) {
// fetch object
...
}
}
}

WHAT SHOULD WE DO WITH THE D***** EXCEPTION
-------------------------------------------
(chorus: WITH THE D***** EXCEPTION)

Obviously File.Open(...) can throw a FileNotFound exception, so should
we catch and discard that? probably not, since we would deprive the
caller of accurate information about what failed.

So, we have to change the declaration of Retrieve:

Object Retrieve(int id): throws FileNotFound {...}

But that doesn't match the interface, and the interface declaration has
to be expanded to include a "throws FileNotFound". This removes the
abstractness of the interface, so you might suggest: "every
implementation of ObjectStore must do some I/O, so we'll let it throw
IOException".

Cutting heels and clipping toes
-------------------------------

This ensnaring argument hides the fundamental problem: you declared the
interface to be implementation-independant in the first place. Even
worse many implementations might NEVER throw an IOException, for example
a test-implementation:

public class MemoryStorage: ObjectStore {
IDictionary objects = new HashTable();
Object Retrieve(int id) throws IOException {
return objects[id]; // cannot throw IOException
}
}

or they might throw a whole new type of exception:

int id_count = 0;
int Store(Object o) {
int id = ++id_count; // ignore concurrency problems for now, ok?
if ( id_count == 0 )
throw new OutOfNamespace(o);
else
objects[id] = o;
}

When it's NOT a feary-tale
--------------------------

In the real world, what you end up with is usually either a global
throws declaration in the interface (and on all the callers of the
interface methods):

Object Retrieve(int id): throws Exception();

Or (nervous ticks starts) every implementation doing:

try {
using ( Stream s =
File.Open(File.Combine(Directory, id.ToString()))) {
// fetch object
...
}
} catch ( Exception e ) {
// an error occured, lot's of info in e, let's throw it away
return null;
}

And a VERY confusing code-style (*mildly* better: Logging errors and
returning null's.)

This is what most JAVA programmers do, atleast in the code i've seen :)

Wrapping extinguish type
------------------------

The last (and worst) alternative (which unfortunatly is done in a lot of
places in .NET) is to wrap the exception:

try {
using ( Stream s =
File.Open(File.Combine(Directory, id.ToString()))) {
// fetch object
...
}
} catch ( Exception e ) {
throw new ObjectStoreException(e);
}

This prevents the caller from even catching on the actual type of
exception occuring, and thus robs him of a viable retry strategy (unless
he wants to traverse the .Inner's of exceptions looking for the real
problem. This would take HEAPS of code, especially if more than one
wrapping is done). It actually removes the whole point of having Types
exceptions :)

*** NOTE: .NET Delegate's do exception wrapping, making catch on a
delegate-invocation a VERY delicate thing to try.

So, while checked exceptions have some nice properties, they really are
tedious to work with when polymorphism is used, since they precisely
expose the implementation differences that you wished to ignore by using
polymorphism.

JAVA
----

Now, zooming in on JAVA: JAVA has excepted that having every exception
as checked is too tedious. In JAVA there are RuntimeException's that may
be thrown *without* declaration in throws statements, and we may even
declare such an exception ourselves, BUT the class heirarchy is used to
indicate whether an exception should be checked or not.

This is higly unfortunate, since it deprives the programmer of the
ability to decide seperatly from situation to situation how "important"
a specific type of exception is, whether it should be catched or not by
the caller.

PROPOSAL
--------

If it was possible to declare "throws" statements on functions and
require callers to either handle or declare the exceptions themselves
(no class-hierarchy spec. of what should be checked here), AND it was
possible to "uncheck" an exception, allowing the caller to knowingly
pass a previously checked exception from a function as unchecked, now
that WOULD be usefull.

It would allow us to write the interface from above in the way we
wanted, without any throws qualifier, but it would allow File.Open to
declare that a FileNotFoundException could reasonably occur and that the
caller should do something about it.

The resulting code would be something like (with a newly invented syntax
for "unchecking", could probably be MUCH ):

using ( Stream s =
uncheck(File.Open(File.Combine(Directory, id.ToString()))),
FileNotFound)
{
// fetch object
...
}

The "uncheck" generates no code, and no catch-handler, it simply
instructs the compiler that the programmer knows that the call to
File.Open may cause an exception, but that should be accepted at
runtime, rather the provably handled by the caller.

CONCLUSION
----------

In this way the intrusion of checked exceptions may be kept to a
tolerable level, and cheked exceptions declarations can be actually
utilized to indicate "hey mate, this might fail, and you better have
something up your sleeve if it does".
 
Mike Schilling said:
. And they're likely to be a lot more specific that "IOException".
Exactly my point.

And my point is that one should hire tech writers to write documentation,
not compiler designers.

John Saunders
 
Back
Top