This is one of those "what if" questions that have been bugging me lately,
so if you're not into that kind of conversation, consider yourself fore-
warned.

I'm trying to understand the possible reasons why filters have been added
to .NET. The reason why this question has some relevance (at least to me)
is that filters seem to be the only thing that *absolutely* require a two-
pass exception handling mechanism. Let me explain what I mean:

Normally, when an exception is thrown, the runtime could start walking
down the stack frame performing local unwind for fault and finally blocks
until it either finds a catch block that matches the exception that was
thrown or it terminates the thread.

The presence of filters in the specification (Partition II, Section
18 "Exception Handling" is what I'm looking at) means that the runtime
must do significantly more. First it needs to walk down the stack in a
first pass to find whether there is a filter willing to handle the
exception (let's call it the filter phase).
The first pass must maintain the original stack due to the (as yet not
implemented) EXCEPTION_CONTINUE_EXECUTION return code, which could
instruct the EE to run the filter and continue the execution at the
instruction following the one that caused the exception. Only after this
first pass happens, the second pass can perform normal, stack destructive
unwinding.

The case pro:

I can see three reasons why having filters makes sense. Unfortunately, I
don't think these reasons are enough and I'd like to hear your collective
opinion:

Pro 1. The handling just described is very similar (the same in fact) with
the way SEH works on Win32. (I vaguely recall reading somewhere that this
style of exception handling provides "continuation semantics"). This being
the case, the original designers of .NET might have felt they should
include it in the runtime.

Pro 2. The second reason might be that VBs On Error / Resume Next
constructs are implemented easier this way. If you go to the trouble of
disassembling a simple On Error program you'll see what I mean.

Pro 3. The third reason might be that this handling can provide a really
cool integration with debuggers - a program that throws an unhandled
exception can bring up a debugger that points to the exact instruction
that threw the exception and still preserve all the stack frames in the
process.

All these are valid reasons I suppose.

The case against is cost and functionality. Cost first:

Against 1. The cost of handling every exception is *in theory* twice the
cost it would have been if filters would not have existed. It is important
to emphasize the difference between theory and practice and I'll get
back to that in a second.

Against 2. The fact that Win32 handles SEH that way could possibly ease
the implementation of exceptions on Windows, but at the same time makes
them harder to implement on non-Windows platforms. Besides, since the EE
engine is an abstraction layer, it is unclear why it would borrow so
heavily from it's primary implementation platform. This refutes point Pro
1. above.

Against 3. On Error/Resume Next is, if not deprecated, at least
discouraged. New constructs that resemble the C#/C++/Java style are the
preferred way VB should handle exceptions. Making such a dramatic
change in order to support a language feature that is already on it's way
out, so to speak, does not seem justified. Moreover, my sense is that
Resume Next can be implemented without filters anyway due
to a language loophole which says that the execution will resume in the
same function that contains the On Error statement (not where the
exception was generated). This point refutes point Pro 2. above.

3. The debugging infrastructure, while cool on its own merit, in theory
should not impose performance penalties on every single exception handling
scenario. Again, this is theory and practice might work differently, but
that's the best I can come up with to refute point Pro 3 above.

Functionality:
4. Neither C++ nor C# from what I can tell (and here I'm looking at
Section 15.10 The try statement of the "C# Specification") (nor Java for
that matter) require this type of construct. Unless there are other
languages out there that absolutely would benefit from this feature, the
cross-language argument does not stand up to scrutiny. (Question to the
group - anybody knows a language that *requires* filters + continuation
semantic like the one offered by .NET's filters? I'm too ignorant to
know :-))

5. In a world where inevitably .NET is compared to Java, it seems that
having a framework that *seems* to require a high cost in handling
exceptions from the get-go is not in the best interest of .NET. (Please,
please, no flames.)

The case for filters could be made much stronger if there is a significant
family of languages out there that would benefit from the type of semantic
available through filters. I don't have knowledge of that family, but
maybe the group does?

Before I go, a note on the difference between theory and practice in
single vs. double pass exceptions:
It is true that a Java JVM would not require a two pass algorithm for
exception handling, but my guess is that it uses one anyway in order to
create a correct stack trace. But that's just guessing on my part.

Thanks for your patience reading this.

Cristian

You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced 
DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to