CA1841: Prefer Dictionary Contains methods
Property | Value |
---|---|
Rule ID | CA1841 |
Title | Prefer Dictionary Contains methods |
Category | Performance |
Fix is breaking or non-breaking | Non-breaking |
Enabled by default in .NET 8 | As suggestion |
Cause
This rule locates calls to a Contains
method on the Keys
or Values
collection of an IDictionary<TKey,TValue> that could be replaced with a call to a ContainsKey
or ContainsValue
method on the dictionary itself.
Rule description
Calling Contains
on the Keys
or Values
collection can often be more expensive than calling ContainsKey
or ContainsValue
on the dictionary itself:
- Many dictionary implementations lazily instantiate the key and value collections, which means that accessing the
Keys
orValues
collection may result in extra allocations. - You may end up calling an extension method on IEnumerable<T> if the keys or values collection uses explicit interface implementation to hide methods on ICollection<T>. This can lead to reduced performance, especially when accessing the key collection. Most dictionary implementations are able to provide a fast O(1) containment check for keys, while the
Contains
extension method on IEnumerable<T> usually does a slow O(n) containment check.
How to fix violations
To fix violations, replace calls to dictionary.Keys.Contains
or dictionary.Values.Contains
with calls to dictionary.ContainsKey
or dictionary.ContainsValue
, respectively.
The following code snippet shows examples of violations, and how to fix them.
using System.Collections.Generic;
// Importing this namespace brings extension methods for IEnumerable<T> into scope.
using System.Linq;
class Example
{
void Method()
{
var dictionary = new Dictionary<string, int>();
// Violation
dictionary.Keys.Contains("hello world");
// Fixed
dictionary.ContainsKey("hello world");
// Violation
dictionary.Values.Contains(17);
// Fixed
dictionary.ContainsValue(17);
}
}
Imports System.Collection.Generic
' Importing this namespace brings extension methods for IEnumerable(Of T) into scope.
' Note that in Visual Basic, this namespace is often imported automatically throughout the project.
Imports System.Linq
Class Example
Private Sub Method()
Dim dictionary = New Dictionary(Of String, Of Integer)
' Violation
dictionary.Keys.Contains("hello world")
' Fixed
dictionary.ContainsKey("hello world")
' Violation
dictionary.Values.Contains(17)
' Fixed
dictionary.ContainsValue(17)
End Sub
End Class
When to suppress warnings
It is safe to suppress warnings from this rule if the code in question is not performance-critical.
Suppress a warning
If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
#pragma warning disable CA1841
// The code that's violating the rule is on this line.
#pragma warning restore CA1841
To disable the rule for a file, folder, or project, set its severity to none
in the configuration file.
[*.{cs,vb}]
dotnet_diagnostic.CA1841.severity = none
For more information, see How to suppress code analysis warnings.