Бөлісу құралы:


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

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

Причина

Это правило обнаруживает вызовы метода 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

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

См. также