Örnekleriniz zaten gösterdiği gibi, bu tür vakaların her biri ayrı ayrı değerlendirilmelidir ve özellikle istisna yönteminiz yeniden kullanılması düşünüldüğünde ve oldukça farklı şekillerde kullanılabiliyorsa "istisnai durumlar" ve "akış kontrolü" arasında belirgin bir gri renk yelpazesi vardır. aslında için tasarlandığından daha. Hepimizin burada, "istisnai olmayan" ın ne anlama geldiğine karar vermesini beklemeyin, özellikle bunu uygulamak için "istisnalar" kullanma ihtimalini hemen tartışırsanız.
Ayrıca, hangi tasarımın kodu okumayı ve sürdürmeyi en kolay hale getirdiği konusunda hemfikir olmayabiliriz, ancak kütüphane tasarımcısının bununla ilgili net bir vizyonu olduğunu ve yalnızca ilgili diğer hususlarla dengelenmesi gerektiğini varsayalım.
Kısa cevap
Oldukça hızlı yöntemler tasarladığınız ve öngörülmeyen yeniden kullanım olasılığını beklediğiniz durumlar dışında, bağırsak hislerinizi takip edin.
Uzun cevap
Gelecekteki her arayan, her iki yönde de istediği gibi hata kodları ve istisnalar arasında serbestçe çeviri yapabilir; bu, iki tasarım yaklaşımını performans, hata ayıklayıcı dostu ve bazı sınırlı birlikte çalışabilirlik bağlamları dışında neredeyse eşdeğer yapar. Bu genellikle performansa kayıyor, bu yüzden buna odaklanalım.
Genel bir kural olarak, bir istisna atmanın normal getiriden 200 kat daha yavaş olmasını bekleyin (gerçekte, bunun önemli bir farkı vardır).
Başka bir kural olarak, bir istisna atmak çoğu zaman sihirli değerlerin en küçüğüne kıyasla daha temiz bir koda izin verebilir, çünkü programcıya birden fazla müşteri kodu katmanına doğru ilerlerken hata kodunu başka bir hata koduna çevirmeye güvenmiyorsunuzdur. Tutarlı ve yeterli bir şekilde ele almak için yeterli bağlamın olduğu bir nokta. (Özel durum: null
burada bazı büyü NullReferenceException
türlerinde kendini otomatik olarak çevirme eğilimi nedeniyle tüm büyü türlerine göre daha iyi ücret alma eğilimindedir , genellikle kusurun kaynağına yakındır, ancak her zaman değil. )
Peki ders nedir?
Bir uygulamanın kullanım ömrü boyunca (uygulamanın başlatılması gibi) yalnızca birkaç kez çağrılan bir işlev için, kodu daha temiz ve anlaşılması daha kolay olan bir şey kullanın. Performans kaygı verici olamaz.
Bir fırlatma fonksiyonu için, size daha temiz kod veren her şeyi kullanın. Ardından, bazı profiller yapın (gerekirse) ve ölçümlere veya genel program yapısına bağlı olarak şüphelenilen üst darboğazlar arasındaysa kodları döndürmek için istisnaları değiştirin.
Pahalı tekrar kullanılabilir bir fonksiyon için, size daha temiz kod veren her şeyi kullanın. Temel olarak her zaman bir ağ gezintisine tabi tutmanız veya diskteki bir XML dosyasını ayrıştırmanız gerekirse, bir istisna atmanın ek yükü büyük olasılıkla ihmal edilebilirdir. "İstisnai olmayan bir başarısızlıktan" daha hızlı bir şekilde geri dönmekten ziyade, herhangi bir hatanın ayrıntılarını kaybetmemek, hatta yanlışlıkla bile önemli değildir.
Yalın yeniden kullanılabilir bir fonksiyon daha fazla düşünce gerektirir. İstihdam istisnalar ederek, vardır zorlayarak fonksiyonun gövdesi çok hızlı çalıştırır eğer, onların (birçok) aramaların yarısında istisna göreceksiniz arayanlar üzerinde yavaşlatmak 100 defa böyle bir şey. İstisnalar hala bir tasarım seçeneğidir, ancak bunu karşılayamayan arayanlar için düşük bir genel gider alternatifi sunmanız gerekecektir. Bir örneğe bakalım.
Dictionary<,>.Item
Gevşek bir şekilde konuşursak, null
değerlerin döndürülmesinden KeyNotFoundException
.NET 1.1 ve .NET 2.0 arasında atmaya kadar değişen harika bir örnek listeliyorsunuz (yalnızca Hashtable.Item
pratik olarak jenerik olmayan öncüsü olmayı düşünmek istiyorsanız ). Bu "değişimin" nedeni burada ilgisiz değil. Değer türlerinin performans optimizasyonu (daha fazla boks yok) orijinal sihir değerini ( null
) bir seçenek haline getirmedi; out
parametreler performans maliyetinin sadece küçük bir kısmını geri getirecektir. Bu ikinci performans değerlendirmesi, fırlatma ek yüküne kıyasla tamamen ihmal edilebilirKeyNotFoundException
, ancak istisna tasarım burada hala üstündür. Neden?
- ref / out parametreleri sadece "arıza" durumunda değil, her zaman maliyetlerini ortaya çıkarır
- Önemseyen herkes
Contains
, indeksleyiciyi aramadan önce arayabilir ve bu desen tamamen doğal olarak okunur. Bir geliştirici aramak istiyor ancak aramayı unutuyorsa Contains
, hiçbir performans sorunu içeri giremez; KeyNotFoundException
farkedilmek ve düzeltilmek için yeterince yüksek.