Sudah menjadi tradisi bahwa pemrogram mengisi tim PVS-Studio memulai pekerjaan mereka dengan menulis artikel tentang menganalisis proyek sumber terbuka. Kali ini, proyek yang terbukti seperti itu adalah Telerik UI untuk UWP.
Penganalisa kode PVS-Studio
PVS-Studio adalah alat untuk mendeteksi kesalahan dan kerentanan potensial dalam kode sumber program yang ditulis dalam C, C ++, C # dan Java. Berjalan di Windows, Linux, dan macOS.
Penganalisis menyediakan berbagai skenario penggunaan:
- dapat digunakan secara lokal pada mesin pengembangan, terintegrasi sebagai plug-in dengan Visual Studio atau IntelliJ IDEA;
- dapat berintegrasi dengan platform jaminan kualitas berkelanjutan SonarQube;
- dapat digunakan secara independen, diintegrasikan ke dalam sistem perakitan;
- dimungkinkan untuk menggunakan utilitas pemantauan kompilasi;
- integrasi dengan Azure DevOps, Jenkins, TeamCity, Travis CI dan sistem serupa dimungkinkan;
- dan sebagainya.
Proyek yang Diaudit
Telerik UI untuk UWP adalah seperangkat komponen antarmuka pengguna untuk Universal Windows Platform (UWP). Kode sumber untuk proyek dapat
ditemukan di Github . Set ini mencakup lebih dari 20 komponen yang memungkinkan Anda untuk memvisualisasikan data dalam bentuk grafik, membuat daftar dan tabel, menggunakan peta untuk menampilkan data yang terkait dengan lokasi.
Fragmen yang menarik perhatian saat mempelajari laporan penganalisa
Peringatan PVS-Studio :
V3013 Aneh bahwa tubuh fungsi 'OnMinValuePropertyChanged' sepenuhnya setara dengan tubuh fungsi 'OnMaxValuePropertyChanged'. RadGauge.cs 446
private static void OnMinValuePropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args) { double newVal = (double)args.NewValue; ValidateValue(newVal); RadGauge gauge = sender as RadGauge; if (gauge.panel != null) { gauge.panel.UpdateOnMinMaxValueChange(); } if(AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged)) { var peer = FrameworkElementAutomationPeer.FromElement(gauge) as RadGaugeAutomationPeer; if (peer != null) { peer.RaiseMinimumPropertyChangedEvent((double)args.OldValue, (double)args.NewValue); } } } private static void OnMaxValuePropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args) { double newVal = (double)args.NewValue; ValidateValue(newVal); RadGauge gauge = sender as RadGauge; if (gauge.panel != null) { gauge.panel.UpdateOnMinMaxValueChange(); } if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged)) { var peer = FrameworkElementAutomationPeer.FromElement(gauge) as RadGaugeAutomationPeer; if (peer != null) { peer.RaiseMinimumPropertyChangedEvent((double)args.OldValue, (double)args.NewValue); } } }
Penganalisa mendeteksi dua metode,
OnMinValuePropertyChanged dan
OnMaxValuePropertyChanged , yang melakukan tindakan yang sama. Saya memiliki kecurigaan kuat bahwa kesalahan telah merayap ke dalam kode ini. Perhatikan bahwa metode
OnMinValuePropertyChanged dan metode
OnMaxValuePropertyChanged menggunakan
RaiseMinimumPropertyChangedEvent . Pada saat yang sama, di kelas
RadGaugeAutomationPeer Anda dapat menemukan metode untuk "Minimum" dan untuk "Maksimum":
internal void RaiseMaximumPropertyChangedEvent(double oldValue, double newValue) { this.RaisePropertyChangedEvent( RangeValuePatternIdentifiers.MaximumProperty, oldValue, newValue); } internal void RaiseMinimumPropertyChangedEvent(double oldValue, double newValue) { this.RaisePropertyChangedEvent( RangeValuePatternIdentifiers.MinimumProperty, oldValue, newValue); }
Metode
RaiseMaximumPropertyChangedEvent tidak pernah digunakan dalam kode, tetapi
RaiseMinimumPropertyChangedEvent digunakan dua kali. Dan, Anda tahu, kinerja metode
OnMaxValuePropertyChanged menimbulkan pertanyaan ... Saya pikir seharusnya menulis yang berikut ini:
private static void OnMaxValuePropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args) { .... peer.RaiseMaximumPropertyChangedEvent((double)args.OldValue, (double)args.NewValue); .... }
Namun demikian, kode tersebut tidak terlihat sangat rapi karena banyaknya elemen berulang. Sulit untuk dipahami, dan kalimat yang berulang-ulang menumpulkan perhatian programmer, dan menjadi lebih sulit untuk melakukan tinjauan kode dalam kondisi seperti itu. Tetapi alat analisis statis melakukan pekerjaan yang sangat baik untuk memeriksa kode tersebut (tetapi ini tidak berarti bahwa Anda dapat melakukannya tanpa refactoring dan terutama tanpa mengurangi jumlah baris yang diulang).
Dari cuplikan kode di atas dan di bawah ini, kita dapat mengasumsikan bahwa penulis tidak menolak untuk menyalin-menempel. Namun, seperti kita semua ... :)
Peringatan PVS-Studio :
V3001 Ada
elemen sub-ekspresi yang identik.RenderSize == emptySize 'ke kiri dan ke kanan' || ' operator. TiltInteractionEffect.cs 181
private static bool IsPointInElementBounds(FrameworkElement element, Point position) { Size emptySize = new Size(0, 0); if (element.RenderSize == emptySize || element.RenderSize == emptySize) { return false; } return new Rect(....).Contains(position); }
Penganalisis mendeteksi fragmen kode kesalahan di mana ke kanan dan ke kiri operator '||'
pernyataan if menggunakan subekspresi yang sama. Subekspresi kedua jelas terlihat berbeda. Mungkin menggantikan
RenderSize kedua yang harus
DiinginkanSize . Atau seharusnya tidak ada subekspresi kedua sama sekali. Bagaimanapun, potongan kode ini perlu diperbaiki.
Peringatan PVS-Studio :
V3001 Ada sub-ekspresi yang identik 'teks [0] ==' - '' di sebelah kiri dan di sebelah kanan '||' operator. RadNumericBox.cs 1057
private void ValidateText() { string text = this.textBox.Text; .... if (text.Length == 1 && (text[0] == '-' || text[0] == '-')) { if (this.isNegative) { this.isNegative = false; } else { this.SetText(string.Empty); } return; } .... }
Di sini, pengembang menulis teks yang dimasukkan dalam bidang kotak teks ke variabel. Kemudian karakter pertama dari string dibandingkan dua kali dengan karakter yang sama '-', yang merupakan keputusan yang mencurigakan. Jelas, validasi teks dalam fungsi ini tidak berfungsi seperti yang dimaksudkan semula.
Peringatan PVS-Studio :
V3001 Ada sub-ekspresi 'newValue.HasValue' yang identik di sebelah kiri dan di sebelah kanan operator '&&'. DateTimePicker.cs 576
private static void OnValueChanged(object sender, DependencyPropertyChangedEventArgs args) { DateTimePicker picker = sender as DateTimePicker; var newValue = (DateTime?)args.NewValue; if (newValue.HasValue && newValue != null)
Ekspresi
newValue.HasValue mengembalikan
true jika
newValue berisi nilai apa pun, dan ekspresi
newValue! = Null melakukan hal yang sama. Penganalisa memperhatikan hal ini, dan apa yang harus dilakukan adalah menghapus salah satu dari subekspresi atau menggantinya dengan yang lain (jika sesuatu yang lain harus diperiksa), tergantung pada keputusan pengembang.
Peringatan PVS-Studio :
V3125 Objek 'CurrentAttachedMenu' digunakan setelah diverifikasi terhadap nol. Periksa baris: 98, 96. PopupService.cs 98
internal static class PopupService { .... private static void Overlay_PointerPressed(....) { if (CurrentAttachedMenu == null || !CurrentAttachedMenu.hitTestService. HitTest(e.GetCurrentPoint(CurrentAttachedMenu).Position).Any()) { CurrentAttachedMenu.IsOpen = false; HideOverlay(); } } }
Jika variabel
CurrentAttachedMenu berubah menjadi
nol , maka evaluasi ekspresi
CurrentAttachedMenu.IsOpen akan
memunculkan exception. Pada pandangan pertama, tampaknya ini adalah salah ketik yang sederhana dan tidak berarti perbandingan dengan
nol , tetapi operasi terbalik - '! ='. Tapi kemudian pengecualian akan terjadi dalam kondisi
pernyataan if jika variabel
CurrentAttachedMenu adalah
nol .
Lebih lanjut dalam kode ada
37 peringatan lain yang sama, beberapa di antaranya tampaknya menunjukkan kesalahan. Tetapi untuk menggambarkannya dalam kerangka satu artikel masih terlalu banyak, jadi saya akan membiarkannya tanpa pengawasan.
Peringatan PVS-Studio :
V3019 Kemungkinan variabel yang salah dibandingkan dengan nol setelah konversi jenis menggunakan kata kunci 'sebagai'. Periksa variabel 'dragDropElement', 'uiDragDropElement'. DragDrop.cs 91
internal static void StartDrag(....) { var dragDropElement = sender as IDragDropElement; .... UIElement uiDragDropElement = dragDropElement as UIElement; .... if (dragDropElement == null || !dragDropElement.CanStartDrag(trigger, initializeContext)) { return; } .... }
Sangat mungkin bahwa penulis mencampur variabel. Ketidaksetaraan
nol diperiksa bukan oleh tautan yang diperoleh sebagai hasil pemeran, tetapi oleh yang asli (
dragDropElement ). Kemungkinan besar, tautan
uiDragDropElement seharusnya
diperiksa . Dugaan ini juga dikonfirmasi oleh fakta bahwa programmer selanjutnya menggunakan
uiDragDropElement tanpa memeriksa
nol .
Peringatan PVS-Studio :
V3030 Pemeriksaan berulang. Kondisi '! ShowIndicatorWhenNoData' sudah diverifikasi di baris 139. RadDataBoundListBox.PullToRefresh.cs 141
internal void HandlePullToRefreshItemStateChanged(object item, ItemState state) { .... bool showIndicatorWhenNoData = this.ShowPullToRefreshWhenNoData; if (this.realizedItems.Count == 0 && !showIndicatorWhenNoData) { if (state == ItemState.Recycled && !showIndicatorWhenNoData) { this.StopPullToRefreshLoading(false); this.HidePullToRefreshIndicator(); } return; } .... }
Penganalisa menemukan sepotong kode di mana, di bawah dua kondisi, variabel
showIndicatorWhenNoData yang sama
diperiksa ulang. Mungkin cek itu hanya mubazir, tetapi ada juga kemungkinan bahwa salah satu subekspresi duplikat harus berbeda sama sekali.
Peringatan PVS-Studio :
V3031 Pemeriksaan berlebihan dapat disederhanakan. '||' Operator dikelilingi oleh ekspresi yang berlawanan. SelectedItemCollection.cs 77
internal class SelectedItemCollection : ObservableCollection<object> { .... private bool CanInsertItem(object item) { return this.suspendLevel == 0 && this.AllowSelect && ((!this.AllowMultipleSelect && this.Count == 0) || this.AllowMultipleSelect); } }
Potongan kode ini tidak salah secara formal. Alat analisa mengisyaratkan beberapa kode redundansi dalam kondisi tersebut. Namun, perlu diingat bahwa kode tambahan kadang-kadang merupakan hasil dari kesalahan, misalnya, ketika alih-alih satu variabel, yang lain diperiksa beberapa kali.
Anda dapat sedikit mengurangi kondisi ini dan menghapus kode tambahan. Misalnya, seperti ini:
internal class SelectedItemCollection : ObservableCollection<object> { .... private bool CanInsertItem(object item) { return this.suspendLevel == 0 && this.AllowSelect && (this.AllowMultipleSelect || this.Count == 0); } }
Pesan serupa lainnya:
- V3031 Pemeriksaan berlebihan dapat disederhanakan. '||' Operator dikelilingi oleh ekspresi yang berlawanan. SelectedItemCollection.cs 93
- V3031 Pemeriksaan berlebihan dapat disederhanakan. '||' Operator dikelilingi oleh ekspresi yang berlawanan. StackVirtualizationStrategy.cs 49
- V3031 Pemeriksaan berlebihan dapat disederhanakan. '||' operator dikelilingi oleh ekspresi berlawanan 'state == null' dan 'state! = null'. LocalFieldDescriptionProviderBase.cs 24
Pertimbangkan potongan kode lain di mana penganalisis mengembalikan yang berikut:
Peringatan PVS-Studio :
- V3137 Variabel 'leftMargin' ditugaskan tetapi tidak digunakan pada akhir fungsi. DragDrop.cs 87
- V3137 Variabel 'topMargin' diberikan tetapi tidak digunakan pada akhir fungsi. DragDrop.cs 88
internal static class DragDrop { .... double leftMargin = 0d; double topMargin = 0d; if (frameworkElementSource != null) { leftMargin = frameworkElementSource.Margin.Left;
Penganalisa melaporkan bahwa
variabel leftMargin dan
topMargin telah diberi nilai, tetapi setelah itu variabel-variabel ini tidak digunakan sampai akhir metode. Mungkin tidak ada kesalahan di sini, tetapi kode tersebut terlihat mencurigakan. Ini mungkin karena kesalahan ketik atau refactoring yang gagal.
Masalah yang sama ditemukan di tempat lain: V3137 Variabel 'currentColumnLength' ditugaskan tetapi tidak digunakan pada akhir fungsi. WrapLayout.cs 824
Peringatan PVS-Studio :
V3061 Parameter 'indeks' selalu ditulis ulang dalam tubuh metode sebelum digunakan. DataEngine.cs 1443
private static Tuple<Group, int> FindGroupAndItemIndex(.... int index, ....) { if (exhaustiveSearch) { .... } else { var aggregateRowGroup = rowRootGroup; var rowGroupNames = valueProvider.GetRowGroupNames(item); foreach (var groupName in rowGroupNames) { Group group; if (aggregateRowGroup.TryGetGroup(groupName, out group)) { aggregateRowGroup = group; } } index = aggregateRowGroup.IndexOf(item,
Parameter
indeks metode
FindGroupAndItemIndex ditimpa sebelum digunakan. Kemungkinan besar, ini menunjukkan kesalahan programmer.
Peringatan PVS-Studio :
V3083 Doa yang tidak aman dari acara 'Selesai', NullReferenceException dimungkinkan. Pertimbangkan menugaskan acara ke variabel lokal sebelum menjalankannya. ActionBase.cs 32
internal abstract class ActionBase { .... protected virtual void OnCompleted() { this.IsCompleted = true; if (this.Completed != null) { this.Completed(this, EventArgs.Empty); } } }
Programmer memungkinkan panggilan yang berpotensi tidak aman ke event handler dalam metode ini, yang dapat menyebabkan pengecualian tipe
NullReferenceException . Pengecualian akan diberikan asalkan antara cek
nol dan panggilan penangan acara, acara ini tidak tetap.
Ada
49 masalah serupa lainnya dalam kode. Tidak akan menarik untuk menonton semuanya di artikel ini, dan penulis akan dapat dengan mudah menemukannya sendiri menggunakan PVS-Studio, jadi kami akan beralih ke kesalahan lain.
PVS-Studio Warning :
V3145 Dereference tidak aman dari target WeakReference, pertimbangkan untuk memeriksa info. Target. Objek tersebut bisa berupa sampah yang dikumpulkan antara memeriksa 'IsAlive' dan mengakses properti 'Target'. FadeAnimation.cs 84
public class RadFadeAnimation : RadAnimation { .... protected internal override void ApplyAnimationValues(PlayAnimationInfo info) { .... if (info.Target.Opacity != opacity)
Penganalisis memperingatkan tentang bahaya pengecualian tipe
NullReferenceException saat mengakses properti
info.Target.Opacity . Untuk lebih memahami esensi masalah, Anda perlu melihat fragmen kelas
PlayAnimationInfo , khususnya, properti
Target .
public class PlayAnimationInfo { .... private WeakReference target; .... public PlayAnimationInfo(Storyboard storyboard, RadAnimation animation, UIElement target) { .... this.target = new WeakReference(target); .... } .... public UIElement Target { get { if (this.target.IsAlive) { return this.target.Target as UIElement; } return null; } } .... }
Secara umum, semakin jauh Anda menggali kode ini, semakin banyak masalah potensial yang dapat Anda temukan di dalamnya. Mari kita lihat mungkin yang paling menarik - yang mana analis mengeluarkan peringatan. Faktanya adalah bahwa bahkan jika eksekusi mengikuti cabang kemudian dari
pernyataan if , ini tidak menjamin bahwa referensi yang tidak nol akan dikembalikan. Terlepas dari percakapan tentang para pemeran, di sini kami menganggap segala sesuatu diizinkan karena inisialisasi objek dalam konstruktor.
Bagaimana ini mungkin? Faktanya adalah bahwa jika antara cek
IsAlive dan Panggilan
target pengumpulan sampah dilakukan, di mana objek yang dirujuk oleh
WeakReference jatuh ,
this.target.Target akan mengembalikan
nol . Yaitu, pemeriksaan
IsAlive tidak menjamin bahwa pada saat
Target diakses, objek masih tersedia.
Omong-omong, situasinya
kembali nol; menangkap aturan diagnostik lain: V3080 Kemungkinan null dereference. Pertimbangkan untuk memeriksa 'info.Target'. FadeAnimation.cs 84
Masalah serupa dalam kode terjadi beberapa kali lagi:
- V3145 dereference tidak aman dari target WeakReference, pertimbangkan memeriksa target. Objek tersebut dapat berupa sampah yang dikumpulkan sebelum properti 'Target' diakses. MoveXAnimation.cs 80
- V3145 dereference tidak aman dari target WeakReference, pertimbangkan memeriksa target. Objek tersebut dapat berupa sampah yang dikumpulkan sebelum properti 'Target' diakses. MoveYAnimation.cs 80
- V3145 Dereferensi tidak aman dari target WeakReference, pertimbangkan untuk memeriksa info. Target. Objek tersebut dapat berupa sampah yang dikumpulkan sebelum properti 'Target' diakses. PlaneProjectionAnimation.cs 244
- V3145 Dereferensi tidak aman dari target WeakReference. Objek tersebut bisa berupa sampah yang dikumpulkan antara memeriksa 'IsAlive' dan mengakses properti 'Target'. WeakEventHandler.cs 109
Mari kita beralih ke contoh berikut.
Peringatan PVS-Studio :
V3066 Kemungkinan urutan argumen yang salah diteruskan ke 'NotifyCollectionChangedEventArgs' konstruktor: 'oldItem' dan 'newItem'. CheckedItemsCollection.cs 470
public class CheckedItemsCollection<T> : IList<T>, INotifyCollectionChanged { .... private NotifyCollectionChangedEventArgs GenerateArgs(....) { switch (action) { case NotifyCollectionChangedAction.Add: .... case NotifyCollectionChangedAction.Remove: .... case NotifyCollectionChangedAction.Replace: return new NotifyCollectionChangedEventArgs( action, oldItem, newItem, changeIndex);
Untuk memahami apa arti peringatan ini dari penganalisa, perlu melihat
parameter konstruktor
NotifyCollectionChangedEventArgs :
public NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction action, object newItem, object oldItem, int index);
Penganalisa memperingatkan bahwa dalam ungkapan
return new NotifyCollectionChangedEventArgs( action, oldItem, newItem, changeIndex);
menukar variabel
oldItem dan
newItem . Dalam definisi konstruktor, mereka terdaftar dalam urutan yang berbeda. Apakah ini dilakukan secara sadar atau tidak, orang hanya bisa menebak.
PVS-Studio Warning :
V3102 Akses mencurigakan ke elemen objek 'x' dengan indeks konstan di dalam satu loop. DataEngine.cs 1718
private class ObjectArrayComparer : IEqualityComparer<object[]> { public bool Equals(object[] x, object[] y) { .... for (int i = 0; i < x.Length; i++) { if (!object.Equals(x[0], y[0]))
Pada setiap iterasi dalam loop, programmer membandingkan
x [0] dan
y [0]. Namun, loop tidak masuk akal dalam kode ini, karena hanya elemen pertama yang dibandingkan. Kemungkinan besar, ini berarti membandingkan elemen array yang sesuai. Maka kode yang benar akan seperti ini:
for (int i = 0; i < x.Length; i++) { if (!object.Equals(x[i], y[i])) { return false; } }
Peringatan PVS-Studio :
V3123 Mungkin
operator '?:' Bekerja dengan cara yang berbeda dari yang diharapkan. Prioritasnya lebih rendah daripada prioritas operator lain dalam kondisinya. EditRowHostPanel.cs 35
protected override Size MeasureOverride(Size availableSize) { .... bool shouldUpdateRowHeight = editorLine == 0 || displayedElement == null ? false : displayedElement.ContainerType != typeof(DataGridGroupHeader); .... }
Peringatan dikaitkan dengan penggunaan Operator '?:'. Ini memiliki prioritas lebih rendah daripada
! =, ||, ==. Oleh karena itu, ekspresi tidak dapat dievaluasi sesuai yang direncanakan oleh programmer. Rupanya, dalam hal ini ini adalah false positive dan kode berfungsi dengan benar. Tetapi membaca kode seperti itu sangat sulit dan tidak pernah ada kepastian bahwa itu dipahami dengan benar. Rasanya seperti pengembang menulis sedemikian rupa sehingga tidak ada yang mengerti apa-apa :) Cara terbaik untuk melakukan ini lebih mudah dibaca - gunakan tanda kurung atau
pernyataan if .
PVS-Studio Warning :
V3078 Order sorting orisinal akan hilang setelah panggilan berulang ke metode 'OrderBy'. Gunakan metode 'ThenBy' untuk mempertahankan penyortiran asli. GridModel.Selection.cs 107
internal partial class GridModel { private void BuildCellSelectionRegions(....) { .... this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .OrderBy(c => c.RowItemInfo.LayoutInfo.Line)); } }
Kesalahan terkait dengan memanggil
OrderBy lagi untuk koleksi tipe
IOrderedEnumerable . Di sini koleksi diurutkan terlebih dahulu oleh kolom, lalu oleh baris. Selain itu, pada saat mengurutkan berdasarkan baris, pengurutan sebelumnya berdasarkan kolom tidak diperhitungkan di mana pun. Agar tidak kehilangan pengurutan menurut kolom dan mengurutkan koleksi berdasarkan beberapa kriteria sekaligus, maka gunakan
ThenBy :
this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .ThenBy(c => c.RowItemInfo.LayoutInfo.Line));
PVS-Studio Warning :
V3008 Variabel 'currentColumnLength' diberi nilai dua kali berturut-turut. Mungkin ini sebuah kesalahan. Periksa baris: 791, 785. WrapLayout.cs 791
private void OnAvailableLengthChanged(double oldValue, double newValue) { .... if (....) { if (currentColumnLength > 0) { var paddingValue = Math.Max(0, newValue - currentColumnLength); this.paddingRenderInfo.Add(paddingValue); currentColumnLength = 0;
Tampaknya mencurigakan bagi penganalisa bahwa variabel
currentColumnLength diberi nilai dua kali. Variabel tidak digunakan di antara tugas. Terlepas dari kondisinya, variabel ini pada akhirnya akan menjadi nol. Kode ini salah atau berlebihan.
Peringatan PVS-Studio :
V3127 Ditemukan dua fragmen kode serupa. Mungkin, ini adalah salah ketik dan variabel 'emptyIconContainer' harus digunakan sebagai ganti 'filledIconContainer' RadRatingItem.cs 240
public class RadRatingItem : RadContentControl { .... protected override void OnApplyTemplate() { .... this.filledIconContainer = this.GetTemplateChild( "FilledIconContainer") as Border; if (this.filledIconContainer == null)
Karena kesalahan ketik, dua kondisi identik muncul dalam kode. Dilihat dari pengecualian yang dihasilkan, kondisi kedua akan terlihat seperti ini:
if (this.emptyIconContainer == null) { throw new MissingTemplatePartException( "EmptyIconContainer", typeof(Border)); }
PVS-Studio Warning :
V3020 'break' tanpa syarat dalam satu loop. NodePool.cs 189
public IEnumerable<KeyValuePair<int, List<T>>> GetUnfrozenDisplayedElements() { foreach (var item in this.generatedContainers) { foreach (var pair in item.Value) { if (!pair.IsFrozen) { yield return item; } break; } } }
Penganalisa menemukan bahwa di sini pernyataan
break bukan milik
pernyataan if .
Break akan dieksekusi terlepas dari nilai
pair.IsFrozen dan karena ini dalam
foreach , hanya satu iterasi yang akan dilakukan.
Itu menyimpulkan pertimbangan saya akan peringatan. Agar pengembang Telerik dapat melakukan analisis kode yang lebih teliti dan memperbaiki cacat, kami siap memberi mereka lisensi sementara. Selain itu, mereka dapat mengambil keuntungan dari penggunaan
bebas opsi
PVS-Studio yang diberikan kepada penulis proyek sumber terbuka.
Kesimpulan
Meskipun pengembang Telerik UI untuk UWP melakukan pekerjaan dengan baik, itu bukan tanpa kesalahan ketik, seperti yang biasanya terjadi :). Semua kesalahan ini dapat dengan mudah ditemukan oleh penganalisa statis dan diperbaiki. Yang paling penting adalah menggunakan penganalisis
dengan benar dan teratur .

Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Ekaterina Nikiforova.
Memeriksa Telerik UI untuk UWP sebagai Cara Memulai dengan PVS-Studio .