[Proposal] Inline/anonymous exception types #4427
Replies: 5 comments 5 replies
-
This is one of the reasons why anonymous types cannot be referenced outside of the method in which they are declared. If you want a type to be reusable across multiple parts of your code, whether that means being passed between methods or thrown/caught, you should be required to explicitly declare that type. The contract of that type is the most important part and I think it decreases readability and the ability to reason about the code if an inline expression can result in the generation of a publicly observable type, and something as simple as a typo can result in generating a completely incompatible type elsewhere. |
Beta Was this translation helpful? Give feedback.
-
For case 1 I think a more general solution would be to allow anonymous types to inherit from other types. if(value < 0)
{
throw new { Value = value } : Exception("this is a message");
} The problem with cases 2 and 3 is if you were trying to type the name of a class that already existed and you mistyped it, instead of telling you the class didn't exist the compiler would create a new class that you didn't intend to create. There would need to be a more explicit way of telling the compiler at the call site to also create the class. The ide already provides a codefix to create the class for you. I think that is sufficient for this case. |
Beta Was this translation helpful? Give feedback.
-
I disagree that this is a helpful thing for the language because it would encourage people to catch (and then handle/discard) Exception explicitly. Most of the time if you are not able to name the exception class , then you probably can't restore your program to a known working state to continue (ie, can you handle a thread-abort exception?) |
Beta Was this translation helpful? Give feedback.
-
I don't understand the point of case 1 whatsoever. Let's supposed that I have By your own design, this would only be intended for Furthermore, could you not achieve case 2 - your main case for this proposal - with Source Generators today? |
Beta Was this translation helpful? Give feedback.
-
Is the "boiler plate" of custom exceptions still a thing? With the removal of multiple App Domains do we really need serializable exception types? That seems to be where the bulk of the boilerplate typically surfaces. Without remoting you can elide the serialization constructor/GetObjectData thus creating pretty compact exception types. Or am I missing something here? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Inline/anonymous exception types
Summary
A lot of boilerplate code is necessary to generate a new exception type. However, most if not all exceptions tend to follow a similar pattern of having a message, an inner exception, and sometimes a couple of properties. In real life, developers tend to follow the easiest path, and having to add new types every time you want an exception is painful. This proposal is looking to resolve that issue, the same way anonymous types and tuples solved the problem of having to generate a full class to hold a few values.
Motivation
Why are we doing this? What use cases does it support? What is the expected outcome?
By removing the requirement of creating a new exception type manually every time a developer needs to add some more info for logging and/or debugging, it would allow for more precise and detailed exceptions without much friction as the developer is implementing a method.
Detailed design
Case 1: Pure anonymous exception
In this case, an anonymous exception would be created the same way an anonymous type is created in .NET. This is for basic cases and should not be used in production except in cases where it is expected to not ever handle this exception other than in a
catch(Exception)
block.or
Case 2: Inline exceptions
This case is the main case for the proposal. The compiler would be responsible to generate the full exception type, with as little code as possible.
Note that in this case, the class
NegativeValueException
is not declared anywhere in the solution other than at the point of throw. By default, the exception would inheritSystem.Exception
and would have the same namespace as the class/method where it is declared.A further option should allow to customize the namespace of the exception by hard-coding the full namespace path before the exception name.
Case 3: Exception inheritance
To allow for exception inheritance, a language feature should allow to set the base type of the exception for inline exceptions. As an idea for implementation, I propose the following:
The compiler would then generate the exception type and make it inherit
ArgumentException
.Constructors
Constructors would be automatically generated based on the inherited type of the inline/anonymous exception. It would be a 1 for 1 mapping of all public constructors. Additional properties to be added on the exception should not appear as a constructor parameter, but as properties with a
public
getter andinit
setter.Serialization
As I am not familiar with exception serialization with the serialization constructor, I leave it open to discussion as to whether or not this should be implemented.
Drawbacks
Such a feature will decentralize exception handing and may lead to unexpected behavior. For instance, two classes in two different projects could have the same inline exception, but because no namespace was specified, they would be considered as two separate exceptions, therefore
catch
clauses might not catch the intended exception.Alternatives
This is purely a quality of life improvement to the language.
Unresolved questions
Design meetings
Beta Was this translation helpful? Give feedback.
All reactions