CA1851: Možné více výčtů IEnumerable
kolekce
Vlastnost | Hodnota |
---|---|
ID pravidla | CA1851 |
Název | Možné více výčtů IEnumerable kolekce |
Kategorie | Výkon |
Oprava způsobující chybu nebo chybu způsobující chybu | Nenarušující |
Zavedená verze | .NET 7 |
Povoleno ve výchozím nastavení v .NET 9 | No |
Příčina
Zjistilo se více výčtů IEnumerable
kolekce.
Popis pravidla
Kolekce typu IEnumerable nebo IEnumerable<T> má schopnost odložit výčet při generování. Mnoho metod LINQ, například Select, používá odložené spuštění. Výčet se spustí, když se kolekce předá do metody výčtu LINQ, jako je ElementAt, nebo použit v příkazu pro každý příkaz. Výsledek výčtu se nevypočítá jednou a ukládá se do mezipaměti, jako je Lazy.
Pokud je samotná operace výčtu nákladná, například dotaz do databáze, více výčtů by poškodilo výkon programu.
Pokud má operace výčtu vedlejší účinky, může mít několik výčtů za následek chyby.
Jak opravit porušení
Pokud je podkladovým typem kolekce IEnumerable
jiný typ, například List
nebo Array
, je bezpečné převést kolekci na základní typ a opravit tak diagnostiku.
Porušení:
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
Oprava:
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
Pokud základní typ IEnumerable
kolekce používá implementaci založenou na iterátoru (například pokud je vygenerována metodami LINQ, jako Select je nebo pomocí klíčového slova výnos ), můžete opravit porušení tím, že kolekci materializujete. Tím se ale přiděluje další paměť.
Příklad:
Porušení:
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
Oprava:
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
Konfigurace přizpůsobených metod výčtu a metod řetězu LINQ
Ve výchozím nastavení jsou všechny metody v System.Linq oboru názvů zahrnuty do oboru analýzy. Můžete přidat vlastní metody, které vyčíslí IEnumerable
argument do oboru nastavením enumeration_methods
možnosti v souboru .editorconfig .
Do oboru analýzy můžete také přidat přizpůsobené metody řetězu LINQ (tj. metody přebírají IEnumerable
argument a vrátit novou IEnumerable
instanci) nastavením linq_chain_methods
možnosti v souboru .editorconfig .
Konfigurace výchozího předpokladu metod přebírá IEnumerable
parametry
Ve výchozím nastavení se předpokládá, že všechny přizpůsobené metody, které přijímají IEnumerable
argument, nejsou výčet argumentu. Můžete to změnit nastavením assume_method_enumerates_parameters
možnosti v souboru .editorconfig .
Kdy potlačit upozornění
Toto upozornění je bezpečné potlačit, pokud je podkladovým typem IEnumerable
kolekce jiný typ, Array
například List
nebo nebo pokud jste si jisti, že metody, které kolekci nevyčtouIEnumerable
, ji nevyčtou.
Potlačení upozornění
Pokud chcete pouze potlačit jedno porušení, přidejte do zdrojového souboru direktivy preprocesoru, abyste pravidlo zakázali a znovu povolili.
#pragma warning disable CA1851
// The code that's violating the rule is on this line.
#pragma warning restore CA1851
Pokud chcete pravidlo pro soubor, složku nebo projekt zakázat, nastavte jeho závažnost v none
konfiguračním souboru.
[*.{cs,vb}]
dotnet_diagnostic.CA1851.severity = none
Další informace naleznete v tématu Jak potlačit upozornění analýzy kódu.