C#idiomatic C#
ca1868fundamentals/code-analysis/quality-rules

Code analysis

CA1868: Unnecessary call to 'Contains' for sets

Learn about code analyzer rule CA1868 - Unnecessary call to 'Contains' for sets

CA1868 Performance enabled by default in .NET 10: As suggestion
Fix is breaking or non-breaking Non-breakingApplicable languages C# and Visual Basic

Cause

An System.Collections.Generic.ISet.Add or System.Collections.Generic.ICollection.Remove call is guarded by a call to System.Collections.Generic.ICollection.Contains. Or, an System.Collections.Immutable.IImmutableSet.Add or System.Collections.Immutable.IImmutableSet.Remove call is guarded by a call to System.Collections.Immutable.IImmutableSet.Contains.

Rule description

Both System.Collections.Generic.ISet.Add() and System.Collections.Generic.ICollection.Remove() perform a lookup, which makes it redundant to call System.Collections.Generic.ICollection.Contains() beforehand. It's more efficient to call System.Collections.Generic.ISet.Add() or System.Collections.Generic.ICollection.Remove() directly, which returns a Boolean value indicating whether the item was added or removed.

This logic also applies to System.Collections.Immutable.IImmutableSet.Add() and System.Collections.Immutable.IImmutableSet.Remove(), except that they either return a new set if the item is added or removed, or the original set if it wasn't.

How to fix violations

Replace the call to System.Collections.Generic.ICollection.Contains() (or System.Collections.Immutable.IImmutableSet.Contains()) that's followed by a call to System.Collections.Generic.ISet.Add() or System.Collections.Generic.ICollection.Remove() (or System.Collections.Immutable.IImmutableSet.Add() or System.Collections.Immutable.IImmutableSet.Remove()) with a single call to the latter method.

Example

The following code snippet shows a violation of CA1868:

csharp
void Run(ISet<string> set)
{
    if (!set.Contains("Hello World"))
    {
        set.Add("Hello World");
    }
}
vb
Sub Run(set As ISet(Of String))
    If Not set.Contains("Hello World") Then
        set.Add("Hello World")
    End If
End Sub

The following code snippet fixes the violation:

csharp
void Run(ISet<string> set)
{
    set.Add("Hello World");
}
vb
Sub Run(set As ISet(Of String))
    set.Add("Hello World")
End Sub

When to suppress warnings

It's safe to suppress this warning if performance isn't a concern.

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.

csharp
#pragma warning disable CA1868
// The code that's violating the rule is on this line.
#pragma warning restore CA1868

To disable the rule for a file, folder, or project, set its severity to none in the configuration file.

ini
[*.{cs,vb}]
dotnet_diagnostic.CA1868.severity = none

For more information, see How to suppress code analysis warnings.