question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

IDE0058 (csharp_style_unused_value_expression_statement_preference) should offer granular (type-specific, method-specific) suppression

See original GitHub issue

Analyzer

Diagnostic ID: IDE0058

Describe the improvement

I’ve found the warnings from IDE0058 to be very helpful in catching cases where return values should be used/inspected or where the call-site should explicitly discard the return value, however there are many types built-in to the .NET Framework / .NET Core / etc (and our own projects and third-party libraries) that have methods that return an insignificant value (i.e. it should be explicitly discarded) but these are APIs where adding an explicit discard would add visual noise.

Examples include StringBuilder.Append(..,) (which returns itself) and many fluent interfaces.

Here’s a screenshot of VS2019 complaining about me ignoring the return value from StringBuilder.Append. I’m sure you’ll agree it’s far too squiggly! - but I don’t want to blindly suppress IDE0058 (either globally or using #pragma warning disable inside each relevant class/method/scope) because I want to be informed of other unintentionally ignored return values on other methods.

image

(I note that I’d prefer it if methods didn’t return this to allow for method-chaining: that’s abusing language semantics for the sake of slightly cleaner syntax - C# should have first-class support for syntax like chaining but without requiring return this (and [return: ] attributes to indicate if a return value actually is this or something else) - but I digress…

Describe suggestions on how to achieve the rule

I think the safest approach would be to allow us to manually specify in .editorconfig every particular method overload where the return-value should be ignored. This may result in a lot of entries being added to .editorconfig though. To provide for a simpler experience there should be a secondary ability to specify a list of method-owner-types (which can include subclasses with inherited methods) for which IDE0058 will be automatically ignored or suppressed.

Therefore I’m proposing the addition of these new entries to .editorconfig for IDE0058:

  • csharp_style_unused_value_assignment_ignore_types
    • Comma-separated list of type-names where all call-sites for all of their methods should be ignored by IDE0058.
  • csharp_style_unused_value_assignment_ignore_types_namespaces
    • Comma-separated list of fully-qualified C# namespaces to search when resolving type-names specified in these new editorconfig properties.
  • csharp_style_unused_value_assignment_ignore_methods
    • Comma-separated list of fully-qualified method overloads (ideally using C# dot syntax, but using alternative syntaxes such as the XML Documentation cref syntax or the .NET fully-qualified type-name (incl generic type backticks and nested-type + path characters) work just as well.
    • The entry should also allow for specifying just the containing type-name and the method-name (i.e. without specifying the exact overload’s parameters) - in this case all matching overloads will be ignored by IDE0058 (e.g. StringBuilder.Append would ignore all overloads of Append whereas StringBuilder.Append(String) would only ignore that specific overload.

Example .editorconfig file:

csharp_style_unused_value_assignment_preference = discard_variable:warning
csharp_style_unused_value_expression_statement_preference = discard_variable:warning

# List the namespaces needed to resolve the type-names specified below (e.g. StringBuilder)
csharp_style_unused_value_assignment_ignore_types_namespaces = System, System.Globalization, System.Text, MyProject

# Ignore IDE0058 on all StringBuilder method call-sites:
csharp_style_unused_value_assignment_ignore_types = StringBuilder    

# Ignore IDE0058 on all overloads of StringBuilder.Append and AppendFormat, and only this specific overload of StringBuilder.Insert:
csharp_style_unused_value_assignment_ignore_methods = StringBuilder.Append, StringBuilder.AppendFormat, StringBuilder.Insert(Int32,Byte)

Additional context

Assuming this is possible, the Code Fixes menu should have new Suppression options to suppress either the call-site’s specific method overload, all methods with the same name, or all methods on the containing type.

Questions

  • Should it be possible to specify specific generic parameter arguments?
    • e.g. if you want to ignore HashSet<String>.Add but not HashSet<Int32>.Add.
  • Given that the syntax for specifying a method overload will include commas , to separate method parameters - but commas are already used to separate values in comma-separated lists in .editorconfig - so how should those commas be disambiguated?
    • One option is to require method-overload specifiers that contain commas to be wrapped in double-quotes (but have double-quotes be optional for specifiers without commas). Is there any alternative?

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:16
  • Comments:5

github_iconTop GitHub Comments

2reactions
uecasmcommented, Mar 13, 2023

As an alternative attribute-based proposal (since I dislike C++'s nodiscard choice), I suggest introducing an attribute [Discardable] (or perhaps [IgnorableReturn] or other bikeshedding) that can be applied either to a method or directly to a return-value to indicate that IDE0058 should not be reported for this return value in particular even when otherwise enabled – but unadorned methods should by default trigger IDE0058 (when enabled).

This should then be applied to the fluent-builder methods and several other places such as collection Add/Remove methods where the return value can be interesting but is not always so. This is usually fairly obvious on a method-by-method basis, when it still makes sense to use the method only for its side effect and not its return. This will take a while to filter down through the library ecosystem once introduced, so the earlier introduced the better, and other suppression techniques can be used in the interim.

1reaction
smailletcommented, Sep 16, 2021

I’d recommend following the C++ model here and support a configuration that ONLY triggers this warning/error if the return attribute NoDiscardAttribute (Or equivalent new attrib) isn’t present. That way method implementers can clearly state that it’s perfectly OK to ignore the return type.

I generally find this warning so obnoxious in the “boy that cried wolf” fashion I just disable it outright.

Read more comments on GitHub >

github_iconTop Results From Across the Web

IDE0058: Remove unnecessary expression value - .NET
Learn about code analysis rule IDE0058: Remove unnecessary expression value.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found