Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

It is sometimes necessary to try/catch exceptions inside the "if" condition, but not the body that follows. In C#, this is really rather cumbersome, requiring locals and code that isn't entirely obvious, at a glance, as to its operation.

It is also sometimes necessary to write "switch" statements, which, unlike "if", have more than two possible outcomes, although in C# this requires the use of a fairly unpopular syntax.

Here's an idea for combining these.

Merging switch with try/catch

First, we change the fundamental syntax of "switch" to be close to that fairly popular replacement, but without the extra curlies:

switch (condition)
    case 1 { }
    case 2 { }
    default { }

Next, we make it possible to catch exceptions in the condition. Under the hood, this inserts an appropriate try/catch block only when at least one catch is present:

switch (condition)
    catch FileNotFoundException e { } // use "e"
    catch ArgumentException { }
    catch { }
    case 1 { }
    case 2 { }
    default { }

Now we make it easier to chain several such statements akin to if/else chaining, by moving "default" one level up, and renaming it to "else":

switch (condition1)
    catch FileNotFoundException { }
    case 1 { }
    case 2 { }
else switch (condition2)
    case "abc" { }
    case "def" { }
else
    { }

And so we have a switch merged with try/catch!

Combining with 'if'

Both switch and if now have else clauses, so why not allow you to mix them as you please:

if (bool-condition1)
    { }
else if (bool-condition2)
    { }
else switch (string-expr)
    catch FileNotFoundException { }
    case "thing" { }
else
    { }

(thanks ach_l!)

Further improvements

Switching on a list or range of values has been proposed and can be easily incorporated:

switch (int-expression)
    case 1 { }
    case 2, 5 { }
    case 10..50 { }
else switch (string-expression)
    case "abc" { }
    case "def" { }
else if (boolean-condition3)
    { }
else
    { }

In this case it could be really convenient to be able to reference the value in the condition clause. This can be easily incorporated by allowing one to declare a single variable in this clause the same way C#'s using allows:

switch (var z = int-expression)
    case 2, 5 { return z == 2 ? "two" : "five"; }
    case 10..50 { return (z * 10).ToString(); }

Benefits

Among other benefits, one can now express a common error-handling scenario concisely, and yet not WTFy:

switch (bool-condition)
    catch FileNotFoundException e { }
    case true { }
    case false { }

Would this solve any real-life coding difficulties you have encountered? Are there any tweaks you would apply to this?

share|improve this question
2  
I have blogged about this before and how cumbersome the differences between if and switch are. I like the way you did it, personally –  Earlz Apr 17 '11 at 4:14
    
I've removed the final step of making if/switch the same statement, and instead incorporated ach_l's idea of allowing one to use them interchangeably. –  romkyns Apr 17 '11 at 10:59
add comment

1 Answer

up vote 3 down vote accepted

Personally I would leave if as evaluating a boolean argument with a true path and optional false else path, whereas switch could evaluate other objects for equality, membership of a set, etc. It may not be a good reason, but this is the behaviour of if in many other languages. To change that definition I think we would risk confusing new programmers.

But I could definately see this syntax of catch blocks being handy, and the ability to chain together ifs and switches might also have a use case.

Personally I tend to like a style where the name of the argument is defined by the block, Additionally, if the value of a condition is being evaluated, we could optionally provide it to the case blocks as well!

Perhaps this example may shed light on the scope of what I'm thinking building on this:

if(<boolean>condition1)
    catch Exception { e -> /* exception referenced by e */ } 
    { /*true*/ } 
else switch(<any>condition2) 
   catch FileNotFoundException { /* I don't care about this exception*/ }
   case 1 {  /* I don't need condition2's value */  }
   case 2, 5, 10 .. 20 { v -> /* v is condition 2 value */ } 
   case <50 { x -> /* x is condition 2's value, this would only be evaluated if other branches are not */}
else 
   { /* !condition1 and no case evaluated in condition 2 */ }
share|improve this answer
    
Regarding the first paragraph: perhaps I didn't make it clear enough, but in this proposal, standard "if"s look exactly the same as before. As for the rest of it - how about the keyword value can be used to access the condition's value, just like in C#'s property setter. –  romkyns Apr 16 '11 at 18:45
2  
@romkyns: Then value can only ever refer to the innermost nested block. Then you’d need extra locals if you need to refer to an outer one, which would be annoying. –  Timwi Apr 16 '11 at 18:51
    
Good point, @Timwi, that would be annoying. if (var z = <condition>) then? –  romkyns Apr 16 '11 at 18:51
    
I like the idea of if/switch in else. It's less controversial and also makes more sense: instead of allowing one to collapse case true just keep if separate. Updated the description. (I'm not so sure about allowing catch on if: if you want that it may be more readable to simply use switch with a catch and a case true clause). –  romkyns Apr 17 '11 at 10:55
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.