You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Allow an abbreviated version of the try syntax in cases in which you expect an exception to be thrown upon evaluation of an expression, but will not make any use of the Exception object besides potentially encapsulating it. The most basic try expression evaluates to a target-typed default if an exception is caught, while the full version leverages pattern-matching on the caught Exception object to determine the value the expression will return.
Examples:
/* Instead of ... */IPAddress?ip=null;try{ip= IPAddress.Parse(input);}catch{}/* This would suffice... */
IPAddress? ip = try IPAddress.Parse(input);/* If an exception was thrown, 'ip' is null (default value) here */
Another common example:
string?value= try Dictionary[key];if(value isnull){return"Not found";}/* The key wasn't in the dictionary */
This works exceptionally well (no pun intended) when combined with the null coalescing operator to provide a safe fallback value:
... or in tandem with throw expressions when you wish to throw your own custom exception.
IPAddressip= try IPAddress.Parse(input)??thrownew ArgumentException("Invalid IP address", nameof(input));
If the caught exception's type needs to be examined to determine a proper fallback value, or if the exception is to be encapsulated in a new exception, the full version, which is similar to a switch expression can be used:
IPAddressip= try (IPAddress.Parse(input)) catch
{FormatException ex =>thrownew ArgumentException("Invalid IP Address", nameof(input), ex),_=> IPAddress.Any
}string?value= try (Dictionary[key]) catch
{KeyNotFoundException =>null,ArgumentNullException ex =>throw ex,Exception ex =>thrownew ConfigurationException("Internal error accessing the configuration store", key, ex)};
Motivation
Because a variable being assigned to during an assignment that may fail needs to be used later on, a traditional try block forces the declaration of the capturing variable to be outside the try block.
Currently, it is not valid to omit the catch block when you have no use for the thrown exception.
Currently, it is not valid to use an expression-bodied try statement.
While multiple successive catch blocks allow for pattern matching of the Exception object, it doesn't allow for the compact syntaxes allowed in switch expressions or even switch statements.
During various routine operations such as input validation, exceptions are expected but the exception objects caught are often unused in code besides potentially being encapsulated or used to determine what type of error occurred. Catch blocks in these circumstances often do not contain more than a throw or the assignment of an alternate value to the original variable.
All of the above contribute to needlessly long try/catch blocks just for the sake of catching parsing and validation errors.
Detailed design
In the above example, the expression try IPAddress.Parse(input) is compiled as if it were:
One drawback is that an exception could be thrown of a type other than the one the developer was intending to catch (and throw away), however this would have happened anyway if the developer is using catch { } or catch (Exception ex) { } today, as is often the case in the places this feature would most commonly be used.
Alternatives
Some other ways to reduce to the boilerplate associated with handling expected exceptions:
Allow the omission of a catch block in which case execution jumps beyond the try block when an exception is caught, however this effectively aborts the assignment rather than evaluating to the default value.
Allow expression-bodied try blocks, although this does not preclude the need to still declare the capturing variable outside of the scope of the try block.
The text was updated successfully, but these errors were encountered:
Try Expressions
Summary
Allow an abbreviated version of the
try
syntax in cases in which you expect an exception to be thrown upon evaluation of an expression, but will not make any use of the Exception object besides potentially encapsulating it. The most basictry
expression evaluates to a target-typeddefault
if an exception is caught, while the full version leverages pattern-matching on the caught Exception object to determine the value the expression will return.Examples:
Another common example:
This works exceptionally well (no pun intended) when combined with the null coalescing operator to provide a safe fallback value:
... or in tandem with throw expressions when you wish to throw your own custom exception.
If the caught exception's type needs to be examined to determine a proper fallback value, or if the exception is to be encapsulated in a new exception, the full version, which is similar to a
switch
expression can be used:Motivation
try
block forces the declaration of the capturing variable to be outside thetry
block.catch
block when you have no use for the thrown exception.try
statement.catch
blocks allow for pattern matching of the Exception object, it doesn't allow for the compact syntaxes allowed inswitch
expressions or evenswitch
statements.throw
or the assignment of an alternate value to the original variable.try
/catch
blocks just for the sake of catching parsing and validation errors.Detailed design
In the above example, the expression
try IPAddress.Parse(input)
is compiled as if it were:Drawbacks
One drawback is that an exception could be thrown of a type other than the one the developer was intending to catch (and throw away), however this would have happened anyway if the developer is using
catch { }
orcatch (Exception ex) { }
today, as is often the case in the places this feature would most commonly be used.Alternatives
Some other ways to reduce to the boilerplate associated with handling expected exceptions:
catch
block in which case execution jumps beyond thetry
block when an exception is caught, however this effectively aborts the assignment rather than evaluating to the default value.try
blocks, although this does not preclude the need to still declare the capturing variable outside of the scope of thetry
block.The text was updated successfully, but these errors were encountered: