-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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: Adding a concise API for throwing exceptions #18907
Comments
I believe CodeContracts has a somewhat similar functionality ? |
@terrajobst thoughts? is this api ready for review? |
If I understand this change correctly, this is happily no longer true: |
@jamesqo with the change @danmosemsft mentions, do you feel like adding such a 'throw helper' class is still something we need to consider? |
There are some potential other advantages of throwing helpers (which is why I used them in other projects even though I was unaware they broke inlining then). Examples
Having said that if the helpers are in the framework these points may be less relevant unless there is something like static callbacks you can set up. Presumably the main motivation is to reduce code size and potentially help inlining, just as ThrowHelper still has value to corelib, it would have the same value to user code. |
@danmosemsft You mentioned in an earlier comment that methods with public static class Error
{
public static ArgumentNullException ArgumentNull(string name) =>
new ArgumentNullException(name);
public static ArgumentOutOfRangeException ArgumentOutOfRange(string name) =>
new ArgumentOutOfRangeException(name);
}
_name = name ?? throw Error.ArgumentNull(nameof(name));
|
@jamesqo I like this approach! I would rename the class to And I am sure we can somehow auto-generate this for all exception types in the framework. |
The outlining codesize optimization like this would be best done by the compilation toolchain ... works for billions lines of existing code, and you do not need to train million developers to write different code to take advantage of it. |
@jkotas 👍 . I am deciding to retarget this again as a convenience-oriented API rather than a perf-oriented one, and also add bulk validation for common patterns, but I feel like I've flip flopped too many times in one proposal. I'll close this and open another one with the new shape I have in mind |
Background
Argument validation is done a lot in .NET code. So much, in fact, that people almost always find that writing
throw new ArgumentNullException(...)
et al. each time is too verbose, and end up writing their own helper classes to throw exceptions. Some random examples I picked from GitHub: Octokit.NET, xUnit, System.Collections.Immutable.Proposal
We should have an API in the BCL for this so people don't have to keep writing their own helper classes. Here's what an initial prototype could look like (similar to the S.C.I class I linked to above):
How it would be used:
Additional Notes
In addition to providing a nice unified API, this may also lead to better performance / decreased memory consumption for .NET apps. Typically when people write their own helper APIs for this, they write it so that the
throw
is in the same clause as the check for the condition, i.e.or, alternatively, they have a method that returns an exception and throw that from the caller:
Code snippet 1 is not likely to be inlined because of the
throw new ...
, whileArgumentNull
in code snippet 2 does get inlined, resulting in generated code bloat for athrow
path that will very rarely get called.If we wrote our own API for throwing exceptions, we could structure it so that the check gets inlined, but the throwing code doesn't:
Thoughts?
cc @svick @benaadams @jkotas @GSPP @mellinoe @KrzysztofCwalina
The text was updated successfully, but these errors were encountered: