Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Pattern-based exception-handling #6789

Closed
alrz opened this issue Nov 15, 2015 · 7 comments
Closed

Proposal: Pattern-based exception-handling #6789

alrz opened this issue Nov 15, 2015 · 7 comments

Comments

@alrz
Copy link
Member

alrz commented Nov 15, 2015

Since catch already has an optional "exception filter", I think it would be reasonable to use patterns also in catch clauses.

specific-catch-clause:
catch ( complex-pattern ) exception-filteropt block

All patterns must be pattern compatible with the type Exception.

try { ... }
catch (WebException { Status is WebExceptionStatus.Timeout } ex) { ... }

Instead of

try { ... }
catch (WebException ex) when (ex.Status == WebExceptionStatus.Timeout) { ... }

If you declare exceptions using record syntax, then you will be able to use recursive-pattern:

class FooException(Status status) : Exception();
catch (FooException(Status.Timeout)) { ... }

With OR patterns (#6235) one should be able to check for multiple exceptions without exception filters.

@stepanbenes
Copy link

@alrz
Copy link
Member Author

alrz commented Nov 15, 2015

@stepanbenes Yeah I know.

@gafter
Copy link
Member

gafter commented Nov 16, 2015

As you have currently specified them, OR patterns require pattern variables to be of the same type on both sides of the disjunction, so using them to catch multiple exception types is not easy.

@alrz
Copy link
Member Author

alrz commented Nov 16, 2015

@gafter I don't know if OR patterns could use the "most common type" rule? (that would be really nice, by the way) However if they could, still, you have to repeat the pattern variable for each exception like catch(E1 ex or E2 ex), and the fact that the identifier in "type patterns" isn't optional makes this not that friendly. As an alternative approach, I think "type intersections" as a general feature would be useful also in this context, catch(E1 & E2) using the regular specific-catch-clause, but in that case if you want to declare a variable, a pair of parentheses would be needed I presume e.g. catch((E1 & E2) ex) which is not that bad. I don't know which approach would be more adoptable to make this possible.

@gafter
Copy link
Member

gafter commented Nov 16, 2015

@alrz if we used the existing dominant type rules, one of the two types would be required to be a subtype of the other. I do not think you would like that.

I think you meant disjunctive, not conjunctive types, as it is only one or the other at any given time. When I did it for Java I used |.

@gafter
Copy link
Member

gafter commented Nov 16, 2015

When I specified and implemented this for Java, you would write

try {
    ...
} catch (NullReferenceException | InvalidCastException ex) {
    ...
}

The type specified in the catch clause can be thought of as a disjunction type. The compiler would emit code to catch precisely those two exception types, and the type of the variable ex within the catch block is a type whose member set is precisely those members that are common to both types.

That works in Java because

  • The "common base type" algorithm is capable of selecting a base type, and
  • The idea of compiling by erasure is well established in the language., and
  • We make the exception parameter readonly so as to avoid specifying too much about the meaning of disjunction types

C#'s "common type" algorithm (as currently specified) never produces a type that is not one of the input types.

@gafter
Copy link
Member

gafter commented Mar 24, 2017

Issue moved to dotnet/csharplang #335 via ZenHub

@gafter gafter closed this as completed Mar 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants