views:

218

answers:

6

Here are two previous questions regarding this topic:

I was working today and thought this might be an appropriate syntax should this feature ever be added to the C# language. Anyone have any opinions about it?

The type of e must be a base type or interface of every exception type listed.

Edit: In this example, the catch block handles either ArgumentNullException or ArgumentOutOfRangeException and places the exception instance in a variable of type ArgumentException called e. It doesn't handle any other type of ArgumentException other than the two listed. I think there was some confusion about the associativity of the , and the as.

Edit 2: If the listed exceptions all upcast to a variable of the type of e, then the code compiles cleanly to MSIL without any casts or explicit type checks, making it faster (potentially significantly) than the current syntax of catching ArgumentException followed by a throw; if it's not one of the two you intended. The problem is even more obvious if you're catching Exception and checking for two possible types to handle and rethrowing if it's something else.

try
{
}
catch (ArgumentNullException, ArgumentOutOfRangeException as ArgumentException e)
{
}
A: 

That would only work if you do not declare an instance (e). If you reference the e inside the block, what is it?

Stu
`e` is obviously an `ArgumentException`, since as I said its type must be a base type of or interface of every listed handled exception. The catch block will not handle any `ArgumentException` other than `ArgumentNullException` and `ArgumentOutOfRangeException`. I actually asked this question specifically because this syntax solved the problem you mention.
280Z28
A: 

I don't find myself wanting this very often in C#, whereas in Java I find there are various situations where I have to catch a bunch of checked exceptions and wrap them all in a different exception that my method is declared to throw.

That's something I'd possibly like some syntax for:

try
{
}
wrap (OneException as AnotherException)
catch (HandleableException e)
{
    // Actual handling for some exception types
}

... but again, I find myself doing that much more in Java than in C#.

There are other enhancements which are way higher up my list for C# than this :)

Jon Skeet
This doesn't handle all `ArgumentException`s, only the two listed. the `as ArgumentException e` gives `e` a type that's guaranteed to be compatible with every possible exception this catch block is declared to handle.
280Z28
Did you edit the question, or did I just miss it? I could have sworn it just listed the three exceptions before. Ah well - editing :)
Jon Skeet
I didn't edit the code, but I added the two marked paragraphs explaining why this might be better than current. There are some APIs (is it ASP.NET?) that require exception handling for many different types of exceptions and I've seen the code get very, very redundant with no simple way to improve it.
280Z28
That's only going to be if you either want to handle or wrap the exception though - I usually just let the exception propagate.
Jon Skeet
A: 

You can already do this, just

 try{}
 catch(Exception e)
 {}

since all exceptions derive from System.Exception. And you would do just as you would above, determine the type of the exception in the catch block itself.

Neil N
That's a workaround for the lack of this feature, and it's specifically discussed in the links I added. I added the **Edit 2** above to address one major benefit of adding language syntax for this use case.
280Z28
Wokrarounds work NOW, how long are you going to wait for a language feature to be added? Assuming it will EVER happen?
Neil N
But that's not the point of this question. I already know how to handle the situation with what's available. Languages evolve over time, taking on characteristics of what people come up with. This will probably never happen (there is a very low statistical rate of feature acceptance), but at least to me it's something to think about. :)
280Z28
+2  A: 

See this:
http://stackoverflow.com/questions/340748/cool-or-stupid-catchexceptionnamingexception-createexception-e

My answer to that question is that they should let you "stack" them like with using blocks:

try
{
}
catch (ArgumentNullException e)
catch (ArgumentOutOfRangeException e)
catch (ArgumentException e)
{

}

Though I see you're going for and rather than or . Personally I don't see the and approach as very useful, because you're already constrained to a real non-interface exception type and there's no dual-inheritance.

Joel Coehoorn
I like this approach as it mimicks how to stack case statements. As long as the coder is willing to determine the type in the catch block as needed.
Neil N
Check my two edits, plus this doesn't address the issue of what type `e` is.
280Z28
I think this would work, but the variable names on the parameters should probably be unique.
Jon Seigel
@Jon then @Joel: Then you end up checking each one for `null`. With mine, you can use the code without checks/casts since you know `e` is a non-null value of type `ArgumentException`. This is a massive difference in terms of code clarity. Also, note that my catch block doesn't handle exceptions of the more general type `ArgumentException`, it just declares `e` as that type since `ArgumentNullException` and `ArgumentOutOfRangeException` both cast to that.
280Z28
@280Z28: In this case, the last `catch` line would be required to be a base type that is a parent of all previous types.
Joel Coehoorn
@280Z28: Now that I think about it, the syntax as given would be allowed, as well as defining each exception variable separately (maybe 2 e's and 1 f). The compiler would simply do its checking for each type that's declared on the same variable.
Jon Seigel
A: 

If ArgumentNullException and ArgumentOutOfRangeException have different interfaces, will be a pain to cast correctly;

For instance ArgumentOutOfRangeException have an ActualValue property; if you had to use it, you'll end with something like:


if(e is ArgumentOutOfRangeException)
{
    // use e.ActualValue
}
else
{
    // use e.Data
}
Rubens Farias
This is for cases where most or all of the code in the catch block is shared for each of the handled exception types.
280Z28
A: 

Inclusion of this feature is planned for Java 7 with the following syntax:

try {  
    return klass.newInstance();  
} catch (InstantiationException | IllegalAccessException e) {  
    throw new AssertionError(e);  
}

Edit: I think the intention is for the static type of e to be the most specific common superclass of the listed exceptions. (In Java, only instances of class java.lang.Throwable can be thrown, hence catching with a common super interface is of limited utility since the exception can not be re-thrown.)

meriton
That proposal is poorly defined because it doesn't address the primary issue of giving a staticly valid type to the variable `e`. The list of handled exceptions (separated in my post by `,` and in the Java proposal by `|`) should be separate from the exception variable declaration type. Mine uses `as` to clearly separate the two. The Java proposal could use `as`, or maybe `catch (InstantiationException | IllegalAccessException : VariableType e)` with the *requirement* that each type in the exception list be castable to `VariableType`.
280Z28