Megosztás a következőn keresztül:


CA1851: A gyűjtemény lehetséges több enumerálása IEnumerable

Tulajdonság Érték
Szabályazonosító CA1851
Cím A gyűjtemény lehetséges több enumerálása IEnumerable
Kategória Teljesítmény
A javítás kompatibilitástörő vagy nem törik Nem törés
Bevezetett verzió .NET 7
Alapértelmezés szerint engedélyezve a .NET 8-ban Nem

Ok

Egy gyűjtemény több enumerálását észlelte IEnumerable .

Szabály leírása

Az IEnumerable vagy az IEnumerable<T> típusú gyűjtemények képesek az enumerálás elhalasztására a létrehozáskor. Számos LINQ-metódus, például a Kiválasztás, halasztott végrehajtást használ. Az enumerálás akkor kezdődik, amikor a gyűjtemény egy LINQ enumerálási metódusba kerül, például az ElementAt metódusba, vagy egy-egy utasításban használatos. Az enumerálási eredmény nem egyszer lesz kiszámítva, és gyorsítótárazva lesz, például Lazy.

Ha maga az enumerálási művelet költséges, például egy adatbázisba irányuló lekérdezés, több enumerálás is rontaná a program teljesítményét.

Ha az enumerálási műveletnek vannak mellékhatásai, több enumerálás is hibákat okozhat.

Szabálysértések kijavítása

Ha a gyűjtemény alapjául szolgáló típus IEnumerable valamilyen más típusú, például List vagy Array, akkor a diagnosztikához biztonságosan átalakíthatja a gyűjteményt a mögöttes típusra.

Szabálysértés:

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

Javítás:

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

Ha a IEnumerable gyűjtemény alapjául szolgáló típus iterátoralapú implementációt használ (például ha linq metódusok, például Select a hozam kulcsszó használatával hozza létre), a gyűjtemény materializálásával kijavíthatja a szabálysértést. Ez azonban további memóriát foglal le.

Például:

Szabálysértés:

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

Javítás:

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

Testreszabott enumerálási módszerek és LINQ-lánc metódusok konfigurálása

Alapértelmezés szerint a System.Linq névtér összes metódusa szerepel az elemzési hatókörben. A .editorconfig fájl beállításával egyéni metódusokat adhat hozzá, amelyek számba adnak egy IEnumerable argumentumot a enumeration_methods hatókörben.

Testre szabott LINQ-lánc metódusokat is hozzáadhat (vagyis a metódusok argumentumot IEnumerable vesznek fel, és egy új IEnumerable példányt adnak vissza) az elemzési hatókörbe egy .editorconfig fájlban lévő beállítás beállításávallinq_chain_methods.

A metódusok alapértelmezett feltételezésének konfigurálása paraméterekkel IEnumerable

Alapértelmezés szerint az argumentumot IEnumerable elfogadó összes testreszabott metódus feltételezi, hogy nem veszi számba az argumentumot. Ezt egy .editorconfig fájl beállításával assume_method_enumerates_parametersmódosíthatja .

Mikor kell letiltani a figyelmeztetéseket?

Ezt a figyelmeztetést nyugodtan letilthatja, ha a IEnumerable gyűjtemény alapjául szolgáló típus más típusú, például List vagy Array, vagy ha biztos abban, hogy a gyűjteményt IEnumerable használó metódusok nem számba veszik.

Figyelmeztetés mellőzése

Ha csak egyetlen szabálysértést szeretne letiltani, adjon hozzá előfeldolgozási irányelveket a forrásfájlhoz a szabály letiltásához és újbóli engedélyezéséhez.

#pragma warning disable CA1851
// The code that's violating the rule is on this line.
#pragma warning restore CA1851

Ha le szeretné tiltani egy fájl, mappa vagy projekt szabályát, állítsa annak súlyosságát none a konfigurációs fájlban.

[*.{cs,vb}]
dotnet_diagnostic.CA1851.severity = none

További információ: Kódelemzési figyelmeztetések letiltása.

Kapcsolódó információk