-
Notifications
You must be signed in to change notification settings - Fork 1k
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: Support Action<Exception> exception handlers with catch clause #831
Comments
@gulshan We already discussed something similar back then on the Roslyn repo Declarative approach to exception handling so you may want to see some of the problems with it that @HaloFour and others are pointing out to me. |
@eyalsk Thanks for pointing. Did not know about it. For me, the overloading was the sweet-spot in this approach, which was not discussed that much in the previous thread. With this approach, error handlers can even be injected. Regarding other disadvantages like not having access to the locals and inability to use Another direction this can take, which I have not mentioned in the proposal as it is out of the current scope. It's about try-catch expressions. Which means both try and catch block will be returning some value. Meaning besides var result = try MethodReturningValue()
catch ( e => { Logger.Log(e); return null; }); In this case, value of result will be var result = try MethodReturningValue() catch ( e => null ); This may require other things like |
And the previous issue was added to backlog by @gafter |
If the goal is reusing exception-handling code, what's wrong with using a method that takes a lambda for the static void HandleException(Exception e) =>
Console.WriteLine(e);
static void HandleException(NullReferenceException e) =>
Console.WriteLine(e);
static void Main(string[] args)
{
try
{
throw new NullReferenceException();
}
catch (HandleException); // Appropriate method overload will be called
} You would write: static void Try(Action action)
{
try
{
action();
}
catch (NullReferenceException e)
{
Console.WriteLine(e);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
static void Main(string[] args)
{
Try(() => throw new NullReferenceException());
} No new syntax required. |
The workaround seems to provide similar functionalities. But they do have differences-
So, it will just be an workaround and not as useful as the proposal. |
If Overload resolution can't happen at runtime, only compile time, so I'm not sure how you were thinking the exception would be dispatched by a single bool HandleException(Exception ex) { ... }
void HandleException(IOException ex) { ... }
try { ... }
catch (Exception ex) when (HandleException(ex)) { }
catch (IOException ex) { HandleException(ex); } 1If multiple catch blocks were autogenerated, one per method in the method group, that could make the overload resolution idea work but would also be a significant departure from the current straightforward behavior of C#. |
@jnm2 Good Catch! And thanks for the solution to the catch also. 😃 |
@jnm2 Well you can always make use of DLR :-) But it is never a good idea to hide it. static void HandleException(Exception e) => Console.WriteLine(e);
static void HandleException(NullReferenceException e) => Console.WriteLine(e);
static void Main(string[] args)
{
try
{
throw new NullReferenceException();
}
catch (HandleException); // Appropriate method overload will be called
} would mean this: catch (Exception ex)
{
dynamic dex = ex;
HandleException(dex);
} Considering exception filters - unfortunately they have a great deal of problems as proposed:
|
Another possible approach is by extending
public class MyExceptionHandler
{
public void Catch(Exception e) => Console.WriteLine(e);
public void Catch(NullReferenceException e) => Console.WriteLine(e);
public void Dispose() => Debug.WriteLine("Exiting using block");
}
...
static void Main(string[] args)
{
using (new MyExceptionHandler())
{
throw new NullReferenceException();
}
} Other benefits are that you can easily carry context into exception handlers and compiler has no problem with staticaly resolving overloads. What do you think? |
@zippec I don't think anyone thinks the DLR is a good idea here :D Your points against the overload resolution are quite good, thankfully, because I don't like that approach. I still don't see why Your exception handler idea is interesting. I'll have to chew on it. I don't dislike it, yet I still don't really see the need. |
@zippec, @jnm2 I think that something like that or similar was proposed back then in the Roslyn repo, could be wrong though hmm what do I think? I don't know how it improves the situation. :) To be honest, I want to have better ways to do exception handling but then when I think about the amount of times I do it I don't have any desire investing thoughts on it, it's a weird area. |
We've had a couple of issues opened up for this idea. I just don't see what these "reusable handlers" provide that benefits the language and the developer. They seem to largely encourage two anti-patterns: log-and-throw and log-and-swallow. Anything beyond that is likely to require additional logic that can't be directly encoded in these handlers. And any useful logging handler is going to require information from the current context anyway which these handlers couldn't access. |
A
catch
block in takes in an exception and performs some action on it. This pattern is very much similar to a lambda of the signatureAction<Exception>
. My proposal is, support lambda exception handler directly with thecatch
clause. This will look like-But lambdas are not my actual focus here. The intent is to define an exception handling method and reuse it. This brings some convenience of code reuse-
The next step will be using overloads to handle different kind of exceptions with separate methods-
Previous discussion: dotnet/roslyn#9539
The text was updated successfully, but these errors were encountered: