CA1841:首选字典包含方法

属性
规则 ID CA1841
标题 首选 Dictionary.Contains 方法
类别 “性能”
修复是中断修复还是非中断修复 非中断
在 .NET 8 中默认启用 作为建议

原因

此规则可找到在 IDictionary<TKey,TValue>KeysValues 集合上对 Contains 方法的调用,这些调用可替换为在字典本身对 ContainsKeyContainsValue 方法的调用。

规则说明

KeysValues 集合调用 Contains 通常比对字典本身调用 ContainsKeyContainsValue 开销更高:

  • 许多字典实现会延迟对键值集合的实例化,这意味着访问 KeysValues 集合可能导致额外的分配。
  • 如果键/值集合使用显式接口实现来隐藏 ICollection<T> 上的方法,可能最终会对 IEnumerable<T> 上调用扩展方法。 这可能会降低性能,尤其是在访问键集合时。 大多数字典实现都能为键提供快速的 O(1) 包含检查,而 IEnumerable<T> 上的 Contains 扩展方法通常执行较慢的 O(n) 包含检查。

如何解决冲突

若要解决冲突,请将对 dictionary.Keys.Containsdictionary.Values.Contains 的调用分别替换为对 dictionary.ContainsKeydictionary.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

有关详细信息,请参阅如何禁止显示代码分析警告

另请参阅