CA1841: предпочтение словарных методов Contains

Свойство Значение
Идентификатор правила CA1841
Заголовок Предпочитать словарь содержит методы
Категория Производительность
Исправление является критическим или не критическим Не критическое
Включен по умолчанию в .NET 8 Как предложение

Причина

Это правило обнаруживает вызовы метода Contains для коллекции Keys или Values из словаря IDictionary<TKey,TValue>, которые можно заменить вызовом метода ContainsKey или ContainsValue непосредственно для словаря.

Описание правила

Вызов Contains для коллекции Keys или Values часто может быть более затратным, чем вызов ContainsKey или ContainsValue для самого словаря.

  • Многие реализации словаря неэкономно создают экземпляры коллекций ключей и значений, из-за чего доступ к коллекции Keys или Values может потребовать дополнительного выделения памяти.
  • Может даже потребоваться вызов метода расширения для IEnumerable<T>, если коллекция ключей или значений использует явную реализацию интерфейса для скрытия методов в ICollection<T>. Это может снизить производительность, особенно при доступе к коллекции ключей. Большинство реализаций словаря позволяют осуществлять в ключах быструю (O(1)) проверку наличия элементов, тогда как метод расширения Contains для IEnumerable<T> обычно выполняет лишь медленную (O(n)).

Устранение нарушений

Для устранения нарушений замените вызовы dictionary.Keys.Contains или dictionary.Values.Contains на вызовы dictionary.ContainsKey или dictionary.ContainsValue соответственно.

В следующем фрагменте кода приведены примеры нарушений и способы их устранения.

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

Когда лучше отключить предупреждения

Можно безопасно скрывать предупреждения по этому правилу, если производительность кода, который его нарушает, не несет критической важности.

Отключение предупреждений

Если вы просто хотите отключить одно нарушение, добавьте директивы препроцессора в исходный файл, чтобы отключить и повторно включить правило.

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

Чтобы отключить правило для файла, папки или проекта, задайте его серьезность none в файле конфигурации.

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

Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.

См. также