Add: extendable production-build assertions #8325
-
Hi all, this is an idea that is nothing new, it's simply a reflection that assertions' implementation in C# .NET is rather poor (there are simpler words for that but I don't want to abuse your hospitality). What I mean specifically by that is that in other languages/frameworks assertions might be removed from production builds but doesn't necessarily have to be removed - while Here I would like to make a note on a conceptual level on why disabling assertions is a very bad idea in the very first place - when a programmer's assertion about the state of the system is incorrect in the production environment, it's still most likely better to crash the system (or at least a single client request) rather than allowing the program to continue. The latter leads to nasty issues, including data corruption and therefore very expensive per-customer fixes (in case you are developing the ootb software). Therefore the assertions should fail the system in a production build. Unfortunately, neither .NET nor language provides anything like Okay, so assertions should fail in production builds in order to avoid expensive per-customer fixes for their data in the ootb solutions case (it's cheaper to fix the software than to fix the software AND some of the customers' data). Now one additional note - all this discussion is about lower level stuff: I am fully aware for close to the client (caller) the data should be validated (as in business logic validation) and proper information for the caller should be returned (potential remediation steps). However deeper down the code we assume (assert) the state of the program, like for example (but not limited to) argument validation with the developer-oriented exceptions (ArgumentNullException) rather than customer-facing exceptions (from their perspective it's "something went wrong, contact your admin or software supplier" type of a problem). Now for these kind of assumptions the code gets very long very quickly: public void Listen(IEnumerable<int> ports)
{
ArgumentNullException.ThrowIfNull(ports); // only possible .NET5+; .NET4.* is still maintained, so it's even more lines there
if (!ports.Any())
{
throw new ArgumentException("List cannot be empty", nameof(ports);
}
if (ports.Any(port => p < 10000 || p > MaxPort)
{
throw new ArgumentException("Invalid port value, any port must be between 10k and MaxPort", nameof(ports));
}
// ... - the actual code of the method
} While, ideally, all this code could be replaced with a one-liner, something like: ports.AssertNotNull().NotEmpty().AllBetween(10000, MaxPort); or in .NET4.* case: ports.AssertNotNull(nameof(ports)).NotEmpty().AllBetween(10000, MaxPort); Hell, let's go crazy and propose not a .NET but a language feature! 😄 assert ports notnull, notempty, inbetween(10000, MaxPort);
// where notnull and notempty are built-in and inbetween is a custom one implemented by a specific project What do you think about this? |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 12 replies
-
|
Beta Was this translation helpful? Give feedback.
-
This does'nt seem to ahve anything to do with hte language. Debug.Assert is a runtime api. And it is stripped out because that's the precise intent of that api, to have no runtime impact. If you want asserts that do run at runtime, you can trivially do that. No need for anythign in the language. |
Beta Was this translation helpful? Give feedback.
-
You can write any kind of DSL you want to validate arguments, and rely on There doesn't need to be a special syntax here, and it'd be extremely impractical to define one for the infinite myriad of potential validations (and combinations of validations) that are used. |
Beta Was this translation helpful? Give feedback.
What you are suggesting is either a language feature or a set of APIs. The language feature will almost certainly not happen. So, the best solution is your initial idea: a set of APIs. Those go in dotnet/runtime.