CA1851: Mogelijke meerdere inventarisaties van IEnumerable
verzameling
Eigenschappen | Weergegeven als |
---|---|
Regel-id | CA1851 |
Titel | Mogelijke meerdere inventarisaties van IEnumerable verzameling |
Categorie | Prestaties |
Oplossing is brekend of niet-brekend | Niet-brekend |
Geïntroduceerde versie | .NET 7 |
Standaard ingeschakeld in .NET 9 | Nee |
Oorzaak
Er zijn meerdere inventarisaties van een IEnumerable
verzameling gedetecteerd.
Beschrijving van regel
Een verzameling van het type IEnumerable of IEnumerable< T> heeft de mogelijkheid om opsomming uit te stellen wanneer deze wordt gegenereerd. Veel LINQ-methoden, zoals Selecteren, gebruiken de uitgestelde uitvoering. Opsomming begint wanneer de verzameling wordt doorgegeven aan een LINQ-opsommingsmethode, zoals ElementAt, of wordt gebruikt in een voor elke instructie. Het opsommingsresultaat wordt niet eenmaal berekend en in de cache opgeslagen, zoals Luie.
Als de opsommingsbewerking zelf duur is, bijvoorbeeld een query in een database, kunnen meerdere opsommingen de prestaties van het programma schaden.
Als de opsommingsbewerking bijwerkingen heeft, kunnen meerdere opsommingen leiden tot bugs.
Schendingen oplossen
Als het onderliggende type van uw IEnumerable
verzameling een ander type is, zoals List
of Array
, is het veilig om de verzameling te converteren naar het onderliggende type om de diagnose te herstellen.
Schending:
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
Oplossing:
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
Als het onderliggende type van de IEnumerable
verzameling gebruikmaakt van een iterator-gebaseerde implementatie (bijvoorbeeld als deze wordt gegenereerd door LINQ-methoden zoals Select of met behulp van het rendementswoord ), kunt u de schending oplossen door de verzameling te materialiseren. Hiermee wordt echter extra geheugen toegewezen.
Voorbeeld:
Schending:
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
Oplossing:
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
Aangepaste opsommingsmethoden en LINQ-ketenmethoden configureren
Standaard worden alle methoden in de System.Linq naamruimte opgenomen in het analysebereik. U kunt aangepaste methoden toevoegen waarmee een IEnumerable
argument in het bereik wordt opgesomd door de enumeration_methods
optie in te stellen in een .editorconfig-bestand .
U kunt ook aangepaste LINQ-ketenmethoden (dat wil gezegd: methoden gebruiken een IEnumerable
argument en een nieuw IEnumerable
exemplaar retourneren) toevoegen aan het analysebereik door de linq_chain_methods
optie in te stellen in een .editorconfig-bestand .
De standaardveronderstelling van methoden configureren, nemen IEnumerable
parameters
Standaard wordt ervan uitgegaan dat alle aangepaste methoden die een IEnumerable
argument accepteren, niet het argument opsommen. U kunt dit wijzigen door de assume_method_enumerates_parameters
optie in te stellen in een .editorconfig-bestand .
Wanneer waarschuwingen onderdrukken
Het is veilig om deze waarschuwing te onderdrukken als het onderliggende type van de IEnumerable
verzameling een ander type is, zoals List
of Array
als u zeker weet dat methoden die een IEnumerable
verzameling nemen, deze niet opsommen.
Een waarschuwing onderdrukken
Als u slechts één schending wilt onderdrukken, voegt u preprocessorrichtlijnen toe aan uw bronbestand om de regel uit te schakelen en vervolgens opnieuw in te schakelen.
#pragma warning disable CA1851
// The code that's violating the rule is on this line.
#pragma warning restore CA1851
Als u de regel voor een bestand, map of project wilt uitschakelen, stelt u de ernst none
ervan in op het configuratiebestand.
[*.{cs,vb}]
dotnet_diagnostic.CA1851.severity = none
Zie Codeanalysewaarschuwingen onderdrukken voor meer informatie.