-
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
[Good Proposal]™ Expression-bodied try catch like get set #1567
Comments
The semicolon ( Single line syntax for get/set is attractive because the implementations are very commonly single line. In my experience, try/catch blocks are quite the opposite. The try part of the statement is typically several lines of code, and if I ever see a single line catch block during a code review it's almost always a sign that something important has been omitted. I'm pretty sure this has been suggested before, but couldn't find it with a brief search. [Aside: I believe the community convention is to use the tag |
With braces with try => DoFizz();
try => DoBuzz();
catch (FooException ex) => HandleFooException(ex);
catch (BarException ex) => HandleBarException(ex);
catch (BazException ex) => HandleBazException(ex); |
You could easily make a utility method to do this for you without needing to modify the language. |
Good proposal but very similar to
|
I also proposed a try-catch expression at #980 |
Well you see that people independent of each other come up with the same idea shows that there is merit in the idea.
Now try that with current state of C# and see how good it looks ;) |
There are a lot of counter-examples that prove this is false. Take your pick. try
{
try
{
Foo();
}
catch(BarException)
{
return null;
}
}
catch(Exception e)
{
Log(e.Message);
} There you go, easy. This isn't hard to read. Of course, there is value in being brief and concise - but that has to be weighed against other constraints as well. Having ideas like this one suggested over and over again doesn't make it them good ideas, just obvious ones. |
Here is the thing how many times do you have to deal with exceptions yourself as opposed to write actual logic? The only reason you get to the same idea is because it's one of the few blocks in the language that doesn't have an expression form and so asking for it is almost inevitable but it doesn't mean something should be done about it. |
How about the following solution (It even works since C# 3.0 !!): public static void @try(this Action body, Action<Exception> single_catch)
{
try
{
body();
}
catch (Exception e)
{
single_catch(e);
}
}
public static void @try(this Action body, params (Predicate<Exception> condition, Action<Exception> body)[] multiple_catch_bodies)
{
try
{
body();
}
catch (Exception e)
{
foreach (var @catch in multiple_catch_bodies)
if (@catch.condition(e))
{
@catch.body(e);
break;
}
}
} This could be used as such: @try(
() => Console.WriteLine(1 / 0),
e => Console.WriteLine("Uh-oh! Some Error occured: " + e.Message)
);
// catch with conditions (like 'when'-clauses)!
@try(
() => Console.WriteLine(File.ReadAllText("/invalid/file_path")),
new (Predicate<Exception>, Action<Exception>)[]
{
(e => e is ArgumentNullException, _ => Console.WriteLine("Argument was null!")),
(e => e is FileNotFoundException, _ => Console.WriteLine("File not found!")),
(e => e is IOException io_ex && io_ex.HResult == 42, e => Console.WriteLine("Something nasty: " + e)),
(_ => true, e => Console.WriteLine("Some other exception: " + e))
}
); |
@Unknown6656 - Sorry, but in my opinion, your
|
That being said, I don't see why people are so bothered by regular In my opinion, the |
Should we label other proposals as |
@Unknown6656 Solves the problem but not as readable as a simple try/catch block. The only utility function like this that I can think of that would make sense and solves a very specific problem in this context and yet readable is what I suggested in this post although even then the downside of maintaining this in every project wouldn't worth the simplicity it brings. |
Yeah, I think OP started off on the wrong foot here... |
All comments so far had in my opinion no compelling arguments. All the negative examples would also apply for get;set where the shorter syntax is objectively better. The only downside is that with short lambda try;catch nesting is not possible, but with the example I have provided the upside is obvious. Also it would make get;set; and try;catch a homogeneus pattern which makes it easier to learn the language. TL;DR: Shorter Syntax, More Readable, More Maintanable, Implementable by Syntactic Sugar |
@dangi12012 I'm trying to help. You're saying, "with the example I have provided the upside is obvious," so what everyone hears is, "You're all missing the obvious." Then you use a title-cased, bold tl;dr with a typo. How do you think this looks from someone else's point of view? I love hearing a compelling argument. Neither of these tactics comes across to me as convincing, any more than leading off by demarking your proposal from everyone else's as a "good proposal." |
I don't know what you're on about but the one that needs to provide a compelling argument is you. I don't want to be harsh but adding
Less marketing statements; more facts. Shorter? yes. More readable? readability means easy to understand and easy to follow and the following code:
although verbose is in my opinion more readable than the proposed version. More maintainable? that's just science fiction. |
Most common expressions have a short and canonical way of expressing a simple statement:
Its so obvious that while the rest of the language evolved to a somewhat less verbose state, |
@stakx @eyalsk , OK, guys. You've got me ;) To my defence, I wrote it only half-heartily and I am not convinced by my own I completely side with you guys on this issue. |
No, it is not at all a special case. Look at the syntax for an if statement. |
No it doesn't. |
I tried, but now I'm dying 🤣 |
Can you explain what this has to do with lambdas? |
catch(BarException) { return null; }
catch(BarException) => return null; You saved exactly 1 character. Forgive me if I don't see the added value. BTW, |
@Neme12 You clearly lack understanding of the language. Just look up the name of the => operator. Please dont spam this thread and try to come up with arguments. "No it doesn't." is not enough for a discussion. Also the advantage is clear for this code:
Support for expression try/catch:
Again: |
I'm not the one making a proposal and I don't have to make arguments to convince anyone. You do, and none of your arguments have been convincing so far. In fact none of them even make sense to me. Do you have anything other than "=> is VERY cool" and "let me save 1 character to avoid this boilerplate"? |
So? If statements haven't evolved either. Lots of things haven't "evolved". |
Yes, if you add tons of whitespace to make the code longer. Whitespace doesn't count as boilerplate to me. |
"This needs to happen" is not enough either. Unless you provide a reason for why it does need to happen, it really doesn't. |
It is not called a "lambda". |
To my mind, this proposal is just trying to paint lipstick on a pig. It proposes slightly different syntax, but doesn't address the issue that throwing exceptions and using At some stage, C# will likely have discriminated union support, coupled with good pattern matching features. At that stage, bool TryFoo(Bar bar, out Foo foo)
{
(var success, foo) = TryBar(bar) switch
{
Success<Bar> s => (true, s.Value),
BarError => (false, null),
Error e => LogErrorAndFail(e)
}
return success;
(bool, Foo) LogErrorAndFail(Error e)
{
Log(e.Message);
return (false, null);
}
} No exceptions and program mechanics-exposing Until then, proposals for tarting up existing syntax seem a bit pointless to me. Forget evolution; we need revolution. |
I think you're treating your code as visual art rather than readable logic. There's a word for those braces: boilerplate. They are fine when you write Hello World but when you have 100 small functions that are each setting up an exception frame, it's a maintenance issue. Unfortunately #616 already figured it out. try/catch/finally should just following the bracing rules of other branching statements, where braces can be omitted with single lines. |
Except that it can't because it's inherently ambiguous. Neither flavor of the syntax resolves that problem. The braces are a necessity to resolve that ambiguity. |
It's not ambiguous if you disallow the embedded statement to be a try statement (the same should have been done for |
@Neme12 , (Image "borrowed" from https://workbea.com/dont-put-lipstick-pig/) |
@HaloFour If it really was necesarry for braces to be there if, else would also disallow it. And for gods sake stop putting memes on this page. |
It probably should have. But an |
While I agree that I'd rather have a |
Well no. Short IS better -> See get;set; if;else; Why not try;catch? There is no reason but its not implemented yet. I guess you can always do with the new type matching: Where also lots of people said it is unnecessary - :sigh
|
When there's a value to it; otherwise, not so much. |
Why apples are not oranges? well... |
@dangi12012 the reason for not doing everything is the team at Microsoft having limited resources to implement everything. A lot of expression-bodied constructs were added to the compiler by a community member. Have you tried implementing expression-bodied try/catch in Roslyn? If you had a PR for that and could show that they don't break existing code and are perfectly legible you would receive a different treatment. |
Well, almost all languages have some version of inline try catch. Ruby especially is Brilliant with the "rescue" keyword. I'm right now trying to delete files which may or may not exists. I don't want to wrap in a try catch.. I would personally recommend a lambda expression like below: This allows the option to do more with the exception, or not if not needed. |
Ok, so I know expression bodies are hot at the moment, but why overcomplicate things. IMO, void CoolMethod() => DoAThing() catch (ChickenDiedException value) Console.WriteLine("Oh no!") catch (Exception e) Console.WriteLine(value.StackTrace); If, however, we wanted to overcomplicate things, syntax could be allowed more modern-looking expression syntax. void CoolMethod() => DoAThing() catch ChickenDiedException with Console.WriteLine("Oh no!") catch var value when ... with Console.WriteLine(value.StackTrace); If we wanted to overcomplicate things to a further extent, then a similar body to the void CoolMethod() => DoAThing() catch
{
var exception when ... => Console.WriteLIne(exception.StackTrace)
}; Instead of |
This would make Try Catch MUCH less verbose to what it is now:
Since C# 6.0 we can have simple Lambda properties:
It would be VERY cool to have this kind of lambda available for Try Catch:
EDIT: This example shows the advantage much cleaner. Try the following code with current state of C#:
If you compare how much boilerplate code was necessary for get;set before C#6.0 you can clearly see how how similar Try Catch is to that. This way code gets less verbose and more readable 👍
What do you think about Expression-bodied try catch?
The text was updated successfully, but these errors were encountered: