CA1851 : Énumérations multiples possibles de la collection IEnumerable
Propriété | Value |
---|---|
Identificateur de la règle | CA1851 |
Titre | Plusieurs énumérations possibles de la collection IEnumerable |
Catégorie | Performances |
Le correctif est cassant ou non cassant | Sans rupture |
Version introduite | .NET 7 |
Activée par défaut dans .NET 9 | Non |
Cause
Détection de plusieurs énumérations d’une collection IEnumerable
.
Description de la règle
Une collection de type IEnumerable ou IEnumerable<T> a la possibilité de différer l’énumération lorsqu’elle est générée. De nombreuses méthodes LINQ, comme Select, utilisent une exécution différée. L’énumération commence lorsque la collection est passée dans une méthode d’énumération LINQ, comme ElementAt, ou utilisée dans une instruction for each. Le résultat de l’énumération n’est pas calculé une seule fois et mis en cache, comme pour Différé.
Si l’opération d’énumération elle-même est coûteuse, par exemple, une requête dans une base de données, plusieurs énumérations nuiraient aux performances du programme.
Si l’opération d’énumération a des effets secondaires, plusieurs énumérations peuvent entraîner des bogues.
Comment corriger les violations
Si le type sous-jacent de votre collection IEnumerable
est un autre type, comme List
ou Array
, il est sûr de convertir la collection en son type sous-jacent pour corriger le diagnostic.
Violation :
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
Correctif :
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
Si le type sous-jacent de la collection IEnumerable
utilise une implémentation avec itérateur (par exemple, si elle est générée par des méthodes LINQ comme Select ou à l’aide du mot clé yield), vous pouvez corriger la violation en matérialisant la collection. Toutefois, cela alloue de la mémoire supplémentaire.
Par exemple :
Violation :
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
Correctif :
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
Configurer des méthodes d’énumération personnalisées et des méthodes de chaîne LINQ
Par défaut, toutes les méthodes de l’espace de noms System.Linq sont incluses dans l’étendue d’analyse. Vous pouvez ajouter des méthodes personnalisées qui énumèrent un argument IEnumerable
dans l’étendue en définissant l’option enumeration_methods
dans un fichier .editorconfig.
Vous pouvez également ajouter des méthodes de chaîne LINQ personnalisées (autrement dit, les méthodes prennent un argument IEnumerable
et retournent une nouvelle instance IEnumerable
) à l’étendue d’analyse en définissant l’option linq_chain_methods
dans un fichier .editorconfig.
Configurer l’hypothèse par défaut que les méthodes prennent des paramètres IEnumerable
Par défaut, toutes les méthodes personnalisées qui acceptent un argument IEnumerable
sont supposées ne pas énumérer l’argument. Vous pouvez modifier cela en définissant l’option assume_method_enumerates_parameters
dans un fichier .editorconfig.
Quand supprimer les avertissements
Il est sûr de supprimer cet avertissement si le type sous-jacent de la collection IEnumerable
est un autre type comme List
ou Array
, ou si vous êtes sûr que les méthodes qui prennent une collection IEnumerable
ne l’énumèrent pas.
Supprimer un avertissement
Si vous voulez supprimer une seule violation, ajoutez des directives de préprocesseur à votre fichier source pour désactiver et réactiver la règle.
#pragma warning disable CA1851
// The code that's violating the rule is on this line.
#pragma warning restore CA1851
Pour désactiver la règle sur un fichier, un dossier ou un projet, définissez sa gravité sur none
dans le fichier de configuration.
[*.{cs,vb}]
dotnet_diagnostic.CA1851.severity = none
Pour plus d’informations, consultez Comment supprimer les avertissements de l’analyse de code.