CA1851: Möjliga flera uppräkningar av IEnumerable
samlingen
Property | Värde |
---|---|
Regel-ID | CA1851 |
Title | Möjliga flera uppräkningar av IEnumerable samlingen |
Kategori | Prestanda |
Korrigeringen är icke-bakåtkompatibel | Icke-icke-bryta |
Introducerad version | .NET 7 |
Aktiverad som standard i .NET 9 | Nej |
Orsak
Flera uppräkningar av en IEnumerable
samling har identifierats.
Regelbeskrivning
En samling av typen IEnumerable eller IEnumerable<T> har möjlighet att skjuta upp uppräkning när den genereras. Många LINQ-metoder, till exempel Select, använder uppskjuten körning. Uppräkning startar när samlingen skickas till en LINQ-uppräkningsmetod, till exempel ElementAt, eller används i en för varje -instruktion. Uppräkningsresultatet beräknas inte en gång och cachelagras, till exempel Lazy.
Om själva uppräkningsåtgärden är dyr, till exempel en fråga till en databas, skulle flera uppräkningar skada programmets prestanda.
Om uppräkningsåtgärden har biverkningar kan flera uppräkningar resultera i buggar.
Så här åtgärdar du överträdelser
Om den underliggande typen av samling IEnumerable
är någon annan typ, till exempel List
eller Array
, är det säkert att konvertera samlingen till dess underliggande typ för att åtgärda diagnostiken.
Överträdelse:
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
Lösningen
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
Om den underliggande typen av IEnumerable
samling använder en iteratorbaserad implementering (till exempel om den genereras av LINQ-metoder som Select eller med nyckelordet yield ) kan du åtgärda överträdelsen genom att materialisera samlingen. Detta allokerar dock extra minne.
Till exempel:
Överträdelse:
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
Lösningen
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
Konfigurera anpassade uppräkningsmetoder och LINQ-kedjemetoder
Som standard ingår alla metoder i System.Linq namnområdet i analysomfånget. Du kan lägga till anpassade metoder som räknar upp ett IEnumerable
argument i omfånget genom att ange enumeration_methods
alternativet i en .editorconfig-fil .
Du kan också lägga till anpassade LINQ-kedjemetoder (dvs. metoder tar ett IEnumerable
argument och returnerar en ny IEnumerable
instans) till analysomfånget linq_chain_methods
genom att ange alternativet i en .editorconfig-fil .
Konfigurera standardantagandet för metoder tar IEnumerable
parametrar
Som standard antas alla anpassade metoder som accepterar ett IEnumerable
argument inte räkna upp argumentet. Du kan ändra detta genom att ange alternativet assume_method_enumerates_parameters
i en .editorconfig-fil .
När du ska ignorera varningar
Det är säkert att ignorera den här varningen om den underliggande typen av IEnumerable
samlingen är någon annan typ som List
eller Array
, eller om du är säker på att metoder som tar en IEnumerable
samling inte räknar upp den.
Ignorera en varning
Om du bara vill förhindra en enda överträdelse lägger du till förprocessordirektiv i källfilen för att inaktivera och aktiverar sedan regeln igen.
#pragma warning disable CA1851
// The code that's violating the rule is on this line.
#pragma warning restore CA1851
Om du vill inaktivera regeln för en fil, mapp eller ett projekt anger du dess allvarlighetsgrad till none
i konfigurationsfilen.
[*.{cs,vb}]
dotnet_diagnostic.CA1851.severity = none
Mer information finns i Så här utelämnar du kodanalysvarningar.