Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
CA1851: возможные несколько перечислений
| Свойство | Значение |
|---|---|
| Идентификатор правила | CA1851 |
| Заголовок | Возможные несколько перечислений IEnumerable коллекции |
| Категория | Производительность |
| Исправление является критическим или не критическим | Не критическое |
| Представленные версии | .NET 7 |
| Включен по умолчанию в .NET 10 | No |
Причина
Обнаружено несколько перечислений IEnumerable коллекции.
Описание правила
Коллекция типов IEnumerable или IEnumerable< T> имеет возможность отложить перечисление при его создании. Многие методы LINQ, такие как Select, используют отложенное выполнение. Перечисление начинается, когда коллекция передается в метод перечисления LINQ, например ElementAt, или используется в каждой инструкции. Результат перечисления не вычисляется один раз и кэшируется, например Lazy.
Если операция перечисления является дорогой, например запрос в базу данных, несколько перечислений повреждют производительность программы.
Если операция перечисления имеет побочные эффекты, несколько перечислений могут привести к ошибкам.
Устранение нарушений
Если базовый тип IEnumerable коллекции является другим типом, например List или Array, можно преобразовать коллекцию в его базовый тип, чтобы исправить диагностику.
Нарушение:
public void MyMethod(IEnumerable<int> input)
{
var count = input.Count();
foreach (var i in input) { }
}
Public Sub MyMethod(input As IEnumerable(Of Integer))
Dim count = input.Count()
For Each i In input
Next
End Sub
Исправление:
public void MyMethod(IEnumerable<int> input)
{
// If the underlying type of 'input' is List<int>
var inputList = (List<int>)input;
var count = inputList.Count();
foreach (var i in inputList) { }
}
Public Sub MyMethod(input As IEnumerable(Of Integer))
' If the underlying type of 'input' is array
Dim inputArray = CType(input, Integer())
Dim count = inputArray.Count()
For Each i In inputArray
Next
End Sub
Если базовый тип IEnumerable коллекции использует реализацию на основе итератора (например, если она создается методами LINQ, например Select или с помощью ключевого слова получения ), можно устранить нарушение, материализуя коллекцию. Однако это выделяет дополнительную память.
Например:
Нарушение:
public void MyMethod()
{
var someStrings = GetStrings().Select(i => string.Concat("Hello"));
// It takes 2 * O(n) to complete 'Count()' and 'Last()' calls, where 'n' is the length of 'someStrings'.
var count = someStrings.Count();
var lastElement = someStrings.Last();
}
Public Sub MyMethod()
Dim someStrings = GetStrings().Select(Function(i) String.Concat(i, "Hello"))
' It takes 2 * O(n) to complete 'Count()' and 'Last()' calls, where 'n' is the length of 'someStrings'.
Dim count = someStrings.Count()
Dim lastElement = someStrings.Last()
End Sub
Исправление:
public void MyMethod()
{
var someStrings = GetStrings().Select(i => string.Concat("Hello"));
// Materialize it into an array.
// Note: This operation would allocate O(n) memory,
// and it takes O(n) time to finish, where 'n' is the length of 'someStrings'.
var someStringsArray = someStrings.ToArray()
// It takes 2 * O(1) to complete 'Count()' and 'Last()' calls.
var count = someStringsArray.Count();
var lastElement = someStringsArray.Last();
}
Public Sub MyMethod()
Dim someStrings = GetStrings().Select(Function(i) String.Concat(i, "Hello"))
' Materialize it into an array.
' Note: This operation would allocate O(n) memory,
' and it takes O(n) time to finish, where 'n' is the length of 'someStrings'.
Dim someStringsArray = someStrings.ToArray()
' It takes 2 * O(1) to complete 'Count()' and 'Last()' calls.
Dim count = someStrings.Count()
Dim lastElement = someStrings.Last()
End Sub
Настройка настраиваемых методов перечисления и методов LINQ chain
По умолчанию все методы в пространстве имен включены в System.Linq область анализа. Можно добавить настраиваемые методы, перечисляющие IEnumerable аргумент в область, задав enumeration_methods параметр в файле editorconfig .
Можно также добавить настраиваемые методы LINQ chain (т. е. методы принимают IEnumerable аргумент и возвращают новый IEnumerable экземпляр) в область анализа, задав linq_chain_methods параметр в файле editorconfig .
Настройка допущения по умолчанию методов принимает IEnumerable параметры
По умолчанию предполагается, что все настраиваемые методы, принимаюющие IEnumerable аргумент, не перечисляют аргумент. Это можно изменить, задав assume_method_enumerates_parameters параметр в файле editorconfig .
Когда лучше отключить предупреждения
Это предупреждение безопасно подавлять, если базовый тип IEnumerable коллекции является другим типом, например List или Array, если вы уверены, что методы, которые IEnumerable принимают коллекцию, не перечисляют его.
Отключение предупреждений
Если вы просто хотите отключить одно нарушение, добавьте директивы препроцессора в исходный файл, чтобы отключить и повторно включить правило.
#pragma warning disable CA1851
// The code that's violating the rule is on this line.
#pragma warning restore CA1851
Чтобы отключить правило для файла, папки или проекта, задайте его серьезность none в файле конфигурации.
[*.{cs,vb}]
dotnet_diagnostic.CA1851.severity = none
Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.