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 9'da 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 Array
gibi 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_parameters
ayarlayarak bunu değiştirebilirsiniz.
Uyarıların ne zaman bastırılması gerekiyor?
Koleksiyonun temel alınan türü veya Array
gibi 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 none
olarak ayarlayın.
[*.{cs,vb}]
dotnet_diagnostic.CA1851.severity = none
Daha fazla bilgi için bkz . Kod analizi uyarılarını gizleme.