www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Chained Catch Statements

reply Jared <v3id9 unb.ca> writes:
In Java and C++, I can do something to the effect of:

try
{
    //Some code
}
catch (Exception1)
{
}
catch (Exception2)
{
}
//etc...

However, this doesn't seem to be possible in D. What is the idiom for handling
a case where multiple exceptions of different types may be thrown?
Jan 30 2012
next sibling parent reply Trass3r <un known.com> writes:
 What is the idiom for handling
 a case where multiple exceptions of different types may be thrown?

I think you could catch a common baseclass like Exception and test if it's a specific Exception by casting.
Jan 30 2012
parent Jared <v3id9 unb.ca> writes:
I suppose that works, though it does seem a little hackish (and I'm pretty sure
it's considered bad form in Java). What was the line of reasoning for omitting
this (to me, at least) extremely useful construct?
Jan 30 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 30 January 2012 at 14:37:19 UTC, Jared wrote:
 In Java and C++, I can do something to the effect of:

That works in D too. I believe it does it linearly though, so it will use the first catch that matches. try {} catch (Exception e) {} // most throwable objects derive from Exception catch (SpecialException e) {} // never used, because Exception matches it all Try putting the more specific catches first, and the generic base classes at the end of the list.
Jan 30 2012
prev sibling next sibling parent Mantis <mail.mantis.88 gmail.com> writes:
30.01.2012 16:37, Jared пишет:
 However, this doesn't seem to be possible in D.

import std.stdio; class Exception1 : Throwable { this( string s ) { super( s ); } } class Exception2 : Throwable { this( string s ) { super( s ); } } void foo() { throw new Exception1( "foo" ); } void bar() { throw new Exception2( "bar" ); } int main() { enum tryBar = false; try { static if( tryBar ) { bar(); } else { foo(); } } catch( Exception1 e1 ) { writeln( "First catch block: ", e1.msg ); } catch( Exception2 e2 ) { writeln( "Second catch block: ", e2.msg ); } return 0; }
Jan 30 2012
prev sibling next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-01-2012 15:37, Jared wrote:
 In Java and C++, I can do something to the effect of:

 try
 {
      //Some code
 }
 catch (Exception1)
 {
 }
 catch (Exception2)
 {
 }
 //etc...

 However, this doesn't seem to be possible in D. What is the idiom for handling
 a case where multiple exceptions of different types may be thrown?

Huh? I do this several places in my code. Works For Me (TM). - Alex
Jan 30 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Monday, 30 January 2012 at 14:50:23 UTC, Adam D. Ruppe wrote:
 On Monday, 30 January 2012 at 14:37:19 UTC, Jared wrote:
 In Java and C++, I can do something to the effect of:

That works in D too. I believe it does it linearly though, so it will use the first catch that matches. try {} catch (Exception e) {} // most throwable objects derive from Exception catch (SpecialException e) {} // never used, because Exception matches it all Try putting the more specific catches first, and the generic base classes at the end of the list.

To me this seems like a mistake. Since likely your catching the current exception and not one of the previously stored ones; A codepath like that should either: A) Fail at compile time, hopefully telling you a suggested order so there's no problems. B) Reorder the catch blocks on it's own during compile time, since only one can get caught at a time anyways. At least that's how I see it.
Jan 30 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/30/12, Era Scarecrow <rtcvb32 yahoo.com> wrote:
 To me this seems like a mistake.

You could throw SpecialException in the handler for Exception. So it's legal code.
Jan 30 2012
prev sibling next sibling parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Monday, 30 January 2012 at 17:17:46 UTC, Andrej Mitrovic wrote:
 On 1/30/12, Era Scarecrow <rtcvb32 yahoo.com> wrote:
 To me this seems like a mistake.

You could throw SpecialException in the handler for Exception. So it's legal code.

Yes, thanks to inheritance it is legal code. However it's almost the same as this, which is legal code too. try { } catch (Throwable t) { } catch {Exception e) { //never executed } catch (StreamException st) { //never executed } //and the list can go on forever. See the problem? Everything that COULD be caught by exception is now caught by throwable since it's inherited. At the very least the compiler should warn you that certain sections won't be executed, But then I would have to manually look up the relationships when the compiler already knows them. In GCC known code blocks that are never executed aren't even compiled in. If the compiler reorders the blocks for you, the above would become this. try { } catch (StreamException st) { //specific case } catch {Exception e) { //less specific but no other inheritances of this kind } catch (Throwable t) { //everything else. }
Jan 30 2012
parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 I do think that having the compiler complain when one catch block hides
 another makes a lot of sense, but I think that that's as far as it should
 go. It's the programmer's job to fix their code, not the compiler's.

I agree. Do we create a new diagnostic enhancement request then? Bye, bearophile
Jan 30 2012
prev sibling next sibling parent "Jesse Phillips" <jessekphillips+D gmail.com> writes:
On Monday, 30 January 2012 at 18:23:56 UTC, Era Scarecrow wrote:
 try {
 } catch (Throwable t) {

 } catch {Exception e) { //never executed

 } catch (StreamException st) { //never executed

 } //and the list can go on forever.

 See the problem?

No? Error: catch at test.d(3) hides catch at test.d(4) The compiler does not reorder the exceptions because it enforces order in the written code. As you say the compiler knows the relationship, the one reading it may not.
Jan 30 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Monday, 30 January 2012 at 19:25:03 UTC, Jesse Phillips wrote:
 On Monday, 30 January 2012 at 18:23:56 UTC, Era Scarecrow wrote:
 try {
 } catch (Throwable t) {

 } catch {Exception e) { //never executed

 } catch (StreamException st) { //never executed

 } //and the list can go on forever.

 See the problem?

No? Error: catch at test.d(3) hides catch at test.d(4) The compiler does not reorder the exceptions because it enforces order in the written code. As you say the compiler knows the relationship, the one reading it may not.

So long as it errors from the hiding (as it appears it does) then it's fine, and the previous example shown was wrong.
 try {}
 catch (Exception e) {} // most throwable objects derive from 
 Exception
 catch (SpecialException e) {} // never used, because 
 Exception matches it all



Jan 30 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/30/12, Era Scarecrow <rtcvb32 yahoo.com> wrote:
 If the compiler reorders the blocks for you

A warning, maybe. But I'm against compilers which try to be too smart and rewrite code to change its semantics. If there's something wrong with my code I want to know about it (warning or error) and fix it, I don't want the compiler rewriting bad code behind-the-scenes. That only encourages writing sloppy code, and I end up having to know implementation details of each compiler to really know what some function body actually does (it could be someone else's code and not just mine).
Jan 30 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, January 31, 2012 01:05:20 Andrej Mitrovic wrote:
 On 1/30/12, Era Scarecrow <rtcvb32 yahoo.com> wrote:
 If the compiler reorders the blocks for you

A warning, maybe. But I'm against compilers which try to be too smart and rewrite code to change its semantics. If there's something wrong with my code I want to know about it (warning or error) and fix it, I don't want the compiler rewriting bad code behind-the-scenes. That only encourages writing sloppy code, and I end up having to know implementation details of each compiler to really know what some function body actually does (it could be someone else's code and not just mine).

I see no reason why the compiler should be reordering anything here. That changes the semantics of the code. It's not like it's a great burden on the programmer to just reorder the blocks so that they're in the correct order. Having the compiler give a warning or error would be plenty, and a lot better than letting the programmer continue to screw up their code in ignorance. If they don't understand how the catch blocks work, they're likely to screw up more than just the order. I do think that having the compiler complain when one catch block hides another makes a lot of sense, but I think that that's as far as it should go. It's the programmer's job to fix their code, not the compiler's. - Jonathan M Davis
Jan 30 2012
prev sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
 I see no reason why the compiler should be reordering anything 
 here. That changes the semantics of the code. It's not like 
 it's a great burden on the programmer to just reorder the 
 blocks so that they're in the correct order. Having the 
 compiler give a warning or error would be plenty, and a lot 
 better than letting the programmer continue to screw up their 
 code in ignorance. If they don't understand how the catch 
 blocks work, they're likely to screw up more than just the 
 order.

 I do think that having the compiler complain when one catch 
 block hides another makes a lot of sense, but I think that 
 that's as far as it should go. It's the programmer's job to fix 
 their code, not the compiler's.

You are right.. I just have wishful thinking of the compiler being smart enough to auto-fix some things, but when you start making assumptions then errors and problems tend to arise more. That and if the compiler DOES reorder those blocks, then you re-ordering them for a specific reason may not work and could have unintended results. Course I don't see how with Try/catch since only one block (plus finally) can be used at a time.
Jan 30 2012