CA1851: possibili enumerazioni di IEnumerable
raccolta
Proprietà | valore |
---|---|
ID regola | CA1851 |
Title | Possibili enumerazioni multiple di IEnumerable raccolta |
Categoria | Prestazioni |
La correzione causa un'interruzione o meno | Non causa un'interruzione |
Versione introdotta | .NET 7 |
Abilitato per impostazione predefinita in .NET 9 | No |
Causa
Rilevate più enumerazioni di una IEnumerable
raccolta.
Descrizione regola
Una raccolta di tipo IEnumerable o IEnumerable< T> può rinviare l'enumerazione quando viene generata. Molti metodi LINQ, ad esempio Select, usano l'esecuzione posticipata. L'enumerazione viene avviata quando la raccolta viene passata in un metodo di enumerazione LINQ, ad esempio ElementAt o usata in un oggetto per ogni istruzione. Il risultato dell'enumerazione non viene calcolato una volta e memorizzato nella cache, ad esempio Lazy.
Se l'operazione di enumerazione stessa è costosa, ad esempio una query in un database, più enumerazioni potrebbero compromettere le prestazioni del programma.
Se l'operazione di enumerazione ha effetti collaterali, più enumerazioni potrebbero causare bug.
Come correggere le violazioni
Se il tipo sottostante della IEnumerable
raccolta è un altro tipo, ad esempio List
o Array
, è possibile convertire la raccolta nel tipo sottostante per correggere la diagnostica.
Violazione:
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
Correzione:
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
Se il tipo sottostante della IEnumerable
raccolta usa un'implementazione basata su iteratore, ad esempio se viene generata da metodi LINQ come Select o usando la parola chiave yield , è possibile correggere la violazione materializzando la raccolta. Tuttavia, alloca memoria aggiuntiva.
Ad esempio:
Violazione:
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
Correzione:
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
Configurare metodi di enumerazione personalizzati e metodi della catena LINQ
Per impostazione predefinita, tutti i metodi nello spazio dei System.Linq nomi sono inclusi nell'ambito di analisi. È possibile aggiungere metodi personalizzati che enumerare un IEnumerable
argomento nell'ambito impostando l'opzione enumeration_methods
in un file con estensione editorconfig .
È anche possibile aggiungere metodi della catena LINQ personalizzati( ovvero i metodi accettano un IEnumerable
argomento e restituiscono una nuova IEnumerable
istanza) all'ambito di analisi impostando l'opzione linq_chain_methods
in un file con estensione editorconfig .
Configurare il presupposto predefinito dei metodi accetta IEnumerable
parametri
Per impostazione predefinita, si presuppone che tutti i metodi personalizzati che accettano un IEnumerable
argomento non enumerino l'argomento. È possibile modificare questa impostazione impostando l'opzione assume_method_enumerates_parameters
in un file con estensione editorconfig .
Quando eliminare gli avvisi
È possibile eliminare questo avviso se il tipo sottostante della IEnumerable
raccolta è un altro tipo, ad List
esempio o Array
, oppure se si è certi che i metodi che accettano una IEnumerable
raccolta non lo enumerino.
Eliminare un avviso
Se si vuole eliminare una singola violazione, aggiungere direttive del preprocessore al file di origine per disabilitare e quindi riabilitare la regola.
#pragma warning disable CA1851
// The code that's violating the rule is on this line.
#pragma warning restore CA1851
Per disabilitare la regola per un file, una cartella o un progetto, impostarne la gravità none
su nel file di configurazione.
[*.{cs,vb}]
dotnet_diagnostic.CA1851.severity = none
Per altre informazioni, vedere Come eliminare gli avvisi di analisi del codice.