Aracılığıyla paylaş


CA1851: Olası birden çok koleksiyon numaralandırması IEnumerable

Özellik Değer
Kural Kimliği CA1851
Başlık Olası birden çok koleksiyon numaralandırması IEnumerable
Kategori Performans
Hataya neden olan veya bozulmayan düzeltme Hataya neden olmayan
Tanıtılan sürüm .NET 7
.NET 8'de varsayılan olarak etkin Hayır

Neden

Bir IEnumerable koleksiyonun birden çok numaralandırması algılandı.

Kural açıklaması

IEnumerable veya IEnumerable< T> türünde bir koleksiyon, oluşturulduğunda numaralandırmayı erteleme özelliğine sahiptir. Select gibi birçok LINQ yöntemi ertelenen yürütmeyi kullanır. Numaralandırma, koleksiyon ElementAt gibi bir LINQ numaralandırma yöntemine geçirildiğinde veya her deyim için bir içinde kullanıldığında başlar. Numaralandırma sonucu bir kez hesaplanmaz ve Gecikmeli gibi önbelleğe alınır.

Numaralandırma işleminin kendisi pahalıysa (örneğin, bir veritabanındaki sorgu), birden çok sabit listesi programın performansına zarar verebilir.

Numaralandırma işleminin yan etkileri varsa, birden çok numaralandırma hatalara neden olabilir.

İhlalleri düzeltme

Koleksiyonunuzun IEnumerable temel türü veya Arraygibi List başka bir türse, tanılamayı düzeltmek için koleksiyonu temel alınan türüne dönüştürmek güvenlidir.

İhlal:

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

Düzeltme:

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

Koleksiyonun IEnumerable temel türü yineleyici tabanlı bir uygulama kullanıyorsa (örneğin, yield anahtar sözcüğünü kullanarak veya gibi Select LINQ yöntemleri tarafından oluşturulduysa), koleksiyonu gerçekleştirerek ihlali düzeltebilirsiniz. Ancak, bu ek bellek ayırır.

Örneğin:

İhlal:

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

Düzeltme:

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

Özelleştirilmiş numaralandırma yöntemlerini ve LINQ zincir yöntemlerini yapılandırma

Varsayılan olarak, ad alanı içindeki System.Linq tüm yöntemler analiz kapsamına dahil edilir. .editorconfig dosyasındaki seçeneğini ayarlayarakenumeration_methods, bir IEnumerable bağımsız değişkeni kapsama numaralandıran özel yöntemler ekleyebilirsiniz.

Ayrıca bir .editorconfig dosyasındaki seçeneği ayarlayarak linq_chain_methods analiz kapsamına özelleştirilmiş LINQ zincir yöntemleri (yani yöntemler bağımsız IEnumerable değişken alır ve yeni IEnumerable bir örnek döndürür) ekleyebilirsiniz.

Parametreleri alan IEnumerable yöntemlerin varsayılan varsayımını yapılandırma

Varsayılan olarak, bağımsız IEnumerable değişkeni kabul eden tüm özelleştirilmiş yöntemlerin bağımsız değişkeni listelemediği varsayılır. Bir .editorconfig dosyasında seçeneğini assume_method_enumerates_parametersayarlayarak bunu değiştirebilirsiniz.

Uyarıların ne zaman bastırılması gerekiyor?

Koleksiyonun temel alınan türü veya Arraygibi List başka bir türse IEnumerable veya koleksiyon alan IEnumerable yöntemlerin bunu listelemediğinden eminseniz, bu uyarıyı gizlemeniz güvenlidir.

Uyarıyı gizleme

Yalnızca tek bir ihlali engellemek istiyorsanız, kuralı devre dışı bırakmak ve sonra yeniden etkinleştirmek için kaynak dosyanıza ön işlemci yönergeleri ekleyin.

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

Bir dosya, klasör veya projenin kuralını devre dışı bırakmak için, yapılandırma dosyasındaki önem derecesini noneolarak ayarlayın.

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

Daha fazla bilgi için bkz . Kod analizi uyarılarını gizleme.

Ayrıca bkz.