Büyü değeri döndür, istisna fırlat veya başarısızlık durumunda yanlış döndür


83

Bazen gerçek bir cevabı değil, başarısızlığı istisnai olmayan bir sınıf kütüphanesi için bir yöntem veya özellik yazmak zorunda kalıyorum . Bir şey belirlenemiyor, mevcut değil, bulunamadı, şu anda mümkün değil veya daha fazla veri yok.

C # 4'teki başarısızlığı belirtmek için nispeten istisnai olmayan bir durum için üç olası çözüm olduğunu düşünüyorum :

  • başka türlü bir anlamı olmayan bir sihir değeri döndürür ( nullve ve gibi -1);
  • bir istisna atmak (örneğin KeyNotFoundException);
  • return falseve gerçek dönüş değerini bir outparametrede (örneğin Dictionary<,>.TryGetValue) verin.

Öyleyse sorular şudur: hangi istisnai olmayan durumda bir istisna atayım? Ve eğer atmamalıysam: ne zaman Try*bir outparametresi olan bir yöntem uygulamak için yukarıda belirtilen sihirli bir değer dönüyor ? (Bana göre outparametre kirli görünüyor ve doğru kullanmak için daha fazla iş var.)

Tasarım kurallarını içeren ( Try*yöntemler hakkında hiçbir şey bilmiyorum ), kullanılabilirlik (bunu bir sınıf kütüphanesi için istediğim gibi), BCL ile tutarlılık ve okunabilirlik gibi gerçek cevaplar arıyorum .


.NET Framework Temel Sınıf Kütüphanesinde, üç yöntem de kullanılır:

HashtableC # 'da jenerik olmadığı zaman yaratıldığı gibi , bunun kullandığı objectve dolayısıyla nullsihirli bir değer olarak geri dönebileceğini unutmayın . Ancak jeneriklerle istisnalar kullanılıyor Dictionary<,>ve başlangıçta yoktu TryGetValue. Görünüşe göre değişim anlayışı.

Açıkçası, Item- TryGetValueve Parse- TryParsedualitenin bir nedeni var, bu yüzden istisnai olmayan başarısızlıklar için istisnalar atmanın C # 4'te yapılmadığını farz ediyorum . Ancak, Try*yöntemler olsa bile, her zaman mevcut Dictionary<,>.Itemdeğildi.


6
"özel durumlar hata anlamına gelir". olmayan bir öğenin sözlüğünü istemek bir hatadır; Akışın bir EOF olduğunda veri okumasını istemek, bir akışı her kullanışınızda olur. (Bu :) ben göndermek için bir şans vermedi uzun bir güzelce biçimlendirilmiş bir cevap özetler)
KutuluMike

6
Sorunun çok geniş olduğunu sanmıyorum, yapıcı bir soru değil. Cevaplar zaten gösterdiği gibi kanonik bir cevap yok.
George Stocker

2
@GeorgeStocker Cevap açık ve net olsaydı, o zaman soruyu sormazdım. İnsanların, belirli bir seçimin neden herhangi bir açıdan (performans, okunabilirlik, kullanılabilirlik, sürdürülebilirlik, tasarım yönergeleri veya tutarlılık gibi) tercih edildiğini iddia edebilmeleri, doğal olarak kanonik olmamasına rağmen memnuniyetimi karşılayabilir. Tüm sorular biraz öznel olarak cevaplanabilir. Anlaşılan iyi bir soru olması için bir sorunun çoğunlukla benzer cevapları olmasını bekliyorsunuz.
Daniel AA Pelsmaeker

3
@ Linklink: George, Stack Overflow'u sürdürmeye yardımcı olmak için zamanının büyük kısmını gönüllü olarak yapan, topluluk tarafından seçilen bir moderatördür. Soruyu neden kapattığını açıkladı ve SSS onu destekledi.
Eric J.

15
Soru, öznel olduğu için değil kavramsal olduğu için buraya aittir . Temel kural: IDE kodlamanızın önünde oturuyorsanız, Yığın Taşması'na sorun. Bir beyaz tahta beyin fırtınası önünde duruyorsanız, buradan Programcılar'dan isteyin.
Robert Harvey,

Yanıtlar:


56

Örneklerinin gerçekten eşdeğer olduğunu sanmıyorum. Davranışları için her biri kendi mantığına sahip üç ayrı grup var.

  1. Sihirli değer, "geçerli" bir koşul StreamReader.Readolduğunda veya hiçbir zaman geçerli bir cevap olmayacak kullanımı basit bir değer olduğunda (-1 için IndexOf) iyi bir seçenektir .
  2. İşlevin semantiği, arayan kişinin çalışacağından emin olması durumunda istisna atar. Bu durumda mevcut olmayan bir anahtar veya hatalı bir çift format gerçekten istisnai bir durumdur.
  3. Bir çık parametresi kullanın ve eğer anlamsal işlem mümkün ise araştırmalıdır.

Verdiğiniz örnekler vaka 2 ve 3 için tamamen açık. Sihir değerleri için, bunun iyi bir tasarım kararı olup olmadığı, her durumda verilemeyeceği söylenebilir.

NaNTarafından döndürülen Math.Sqrtözel bir durumdur - bu kayan nokta standardına uygundur.


10
1 numaraya katılmıyorum Ayrıca okunabilirliği de incitiyorlar. Büyü değerinin kullanımının Try modelinden daha iyi olmadığı bir örnek düşünemiyorum.
0b101010

1
Peki ya Either<TLeft, TRight>monad?
sara,

2
@ 0b101010: streamreader.read'in güvenle nasıl -1 döndüğünü ararken biraz zaman harcadı ...
jmoreno

33

API kullanıcısına ne yapmaları gerektiği hakkında iletişim kurmaya çalışıyorsunuz. Bir istisna atarsanız, onları yakalamaya zorlayan hiçbir şey yoktur ve yalnızca belgeyi okumak, tüm olasılıkların ne olduğunu bilmelerini sağlar. Şahsen, belirli bir yöntemin yol açabileceği tüm istisnaları bulmak için dokümantasyona girmeyi yavaş ve sıkıcı buluyorum (intellisense olsa bile, bunları manuel olarak kopyalamak zorundayım).

Büyü değeri, hala belgeleri okumanızı constve değeri çözmek için bazı tablolara başvurmanızı gerektirir. En azından istisnai olmayan bir durum olarak adlandırdığınız şeyin istisna yükü yoktur.

Bu yüzden outparametreler bazen kaşlarını çatmasa da, Try...sözdizimi ile bu yöntemi tercih ederim . Kanonik .NET ve C # sözdizimi. API kullanıcısına, sonucu kullanmadan önce dönüş değerini kontrol etmeleri gerektiğini bildirirsiniz. Ayrıca outhata ayıklamaya yardımcı olan, yararlı bir hata mesajı içeren ikinci bir parametre de ekleyebilirsiniz . Bu yüzden Try...ile outparametre çözümü için oy kullanıyorum .

Başka bir seçenek de, bunu çok daha sıkıcı bulmama rağmen, özel bir "sonuç" nesnesi döndürmek:

interface IMyResult
{
    bool Success { get; }
    // Only access this if Success is true
    MyOtherClass Result { get; }
    // Only access this if Success is false
    string ErrorMessage { get; }
}

Sonra fonksiyonunuz doğru görünüyor çünkü sadece giriş parametreleri var ve sadece bir şey döndürüyor. Sadece döndürdüğü tek şey bir çeşit para.

Aslında, eğer böyle bir şeyle karşılaşıyorsanız, Tuple<>.NET 4'te tanıtılan yeni sınıfları kullanabilirsiniz . Şahsen, her alanın anlamının daha az açık olması hoşuma gitmiyor, çünkü veremiyorum. Item1ve Item2faydalı isimler.


3
Şahsen, genellikle sizin ya da sonuç değerinden IMyResultdaha karmaşık bir sonuç iletmek mümkün olduğundan sizin gibi bir sonuç kabı kullanıyorum . int dizgisine dönüştürmek gibi basit şeyler için kullanışlıdır. truefalseTry*()
this.myself

1
İyi yazı. Benim için, "return" değerleri ile "out" parametreleri arasında ayrım yapmak yerine yukarıda ana hatlarıyla belirtilen Sonuç yapı deyimini tercih ediyorum. Düzgün ve düzenli tutar.
Ocean Airdrop

2
İkinci çıkış parametresindeki sorun, karmaşık bir programda 50 işlev derinliğinde olduğunuzda, bu hata iletisini kullanıcıya nasıl iletirsiniz? Bir istisna atmak, kontrol hatalarının katmanlarından çok daha basittir. Bir tane aldığınızda sadece onu atın ve ne kadar derin olduğunuz önemli değil.
rulo

@ rolls - Çıktı nesnelerini kullandığımızda, hemen arayan kişinin çıktıyla istediğini yapabileceğini varsayarız: yerel olarak davranın, yok sayın veya bir istisna içine attırarak kabarcıklı olun. Her iki kelimenin de en iyisidir - arayan kişi olası tüm çıktıları net bir şekilde görebilir (enums vb. İle), hatayla ne yapılacağına karar verebilir ve her aramada yakalamaya gerek yoktur. Çoğunlukla sonucu hemen ele almayı veya görmezden gelmeyi bekliyorsanız, nesneleri döndürmek daha kolaydır. Tüm hataları üst katmanlara atmak istiyorsanız, istisnalar daha kolaydır.
drizin

2
Bu sadece C # 'daki kontrol edilen istisnaları Java' daki kontrol edilen istisnalar dışında çok daha sıkıcı bir şekilde yeniden icat ediyor.
Kış

17

Ö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: nullburada bazı büyü NullReferenceExceptiontü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<,>.ItemGevşek bir şekilde konuşursak, nulldeğ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.Itempratik 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; outparametreler 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; KeyNotFoundExceptionfarkedilmek ve düzeltilmek için yeterince yüksek.

Bence 200x istisnaların mükemmelliği konusunda iyimser oluyor ... yorumlardan hemen önce blogs.msdn.com/b/cbrumme/archive/2003/10/01/51524.aspx "Performans ve Trendler" bölümüne bakın.
gbjbaanb

@gbjbaanb - Belki de. Bu makale tamamen farklı bir oyun alanı olmayan konuyu tartışmak için% 1 başarısızlık oranı kullanıyor. Kendi düşüncelerim ve belirsiz bir şekilde hatırladığım ölçümler, tablo uygulanan C ++ bağlamından olacaktır ( bu raporun 5.4.1.2. Bölümüne bakınız) ; buradaki bir problem, türünün ilk istisnasının bir sayfa hatasıyla başlaması muhtemeldir (sert ve değişken ama bir kez ek yükü düşürdüm.) Fakat .NET 4 ile bir deney yapacağım ve deneyeceğim ve muhtemelen bu basketbol değerini değiştireceğim. Zaten varyansı vurguladım.
Jirka Hanika

Ref / out parametrelerinin maliyeti o zaman yüksek mi? Nasıl yani? Ve Containsbir indeksleyiciyi aramadan önce çağırmak, olması gerekmeyen bir yarış durumuna neden olabilir TryGetValue.
Daniel AA Pelsmaeker

@gbjbaanb - Deneme tamamlandı. Tembeldim ve Linux'ta mono kullandım. İstisnalar , 3 saniyede ~ 563000 atış verdi. İade 3 saniyede ~ 10900000 getiri verdi. 1:20, 1: 200 bile değil. Daha gerçekçi bir kod için hala 1: 100+ düşünmeyi öneririm. (out param varyantı, tahmin ettiğim gibi, ihmal edilebilir maliyetlere sahipti
İmtiyaz

@ Link Link - Genel olarak iplik güvenliği konusunda anlaşmaya varıldı, ancak özellikle .NET 4'e atıfta bulunduğunuz ConcurrentDictionaryiçin, çok Dictionarydişli erişim için ve optimum performans için tek dişli erişim için kullanın. Yani `` Contains '' kullanmamak, kod dizisini bu belirli Dictionarysınıfla güvenli hale getirmez .
Jirka Hanika

10

Böylesine istisnai olmayan bir durumda başarısızlığı belirtmek için yapılacak en iyi şey nedir ve neden?

Başarısızlığa izin vermemelisin.

Biliyorum, el dalgalı ve idealist ama beni dinle. Tasarım yaparken, başarısızlık modları olmayan bir sürümü tercih etme şansına sahip olduğunuz bazı durumlar vardır. LINQ başarısız olan bir 'FindAll'a sahip olmak yerine, sadece boş bir numaralandırılabilir döndüren bir where cümlesini kullanır. Kullanılmadan önce başlatılması gereken bir nesneye sahip olmak yerine, yapıcının nesneyi başlatmasına izin verin (veya başlatılmadığında algılandığında başlat). Anahtar, tüketici branşındaki başarısızlık dalını kaldırmaktır. Sorun bu, buna odaklanın.

Bunun için bir başka strateji de KeyNotFoundsscenario. 3.0'dan beri çalıştığım hemen hemen her kod tabanında, bu uzantı yöntemine benzer bir şey var:

public static class DictionaryExtensions {
    public static V GetValue<K, V>(this IDictionary<K, V> arg, K key, Func<K,V> ifNotFound) {
        if (!arg.ContainsKey(key)) {
            return ifNotFound(key);
        }

        return arg[key];
    }
}

Bunun için gerçek bir başarısızlık modu yok. ConcurrentDictionarybenzer bir GetOrAddyapıya sahiptir.

Bütün bunlar, daima kaçınılmaz olduğu zamanlar olacak. Üçünün de bir yeri var, ama ilk seçeneği tercih ederim. Tüm bunlar null tehlikesiyle karşı karşıya olmasına rağmen, iyi bilinmektedir ve “istisnai olmayan başarısızlık” setini oluşturan “bulunamayan” veya “sonuç uygulanamaz” senaryolarının çoğuna uyar. Özellikle null değeri olan tipler yaparken, “bu başarısız olabilir” in önemi kodda çok açık ve unutulması / sökülmesi zor.

İkinci seçenek, kullanıcı aptalca bir şey yaptığında yeterince iyidir. Size yanlış formatı olan bir dize verir, tarihi 42 Aralık'a ayarlamaya çalışır ... test sırasında kötü kodun tanımlanması ve düzeltilmesi için işlerin hızlı ve çarpıcı şekilde patlamasını istediğiniz bir şeydir.

Son seçenek giderek daha fazla sevmediğim bir seçenek. Out parametreleri zordur ve yöntemlere bakarken, bir şeye odaklanmak ve yan etkileri olmamak gibi en iyi uygulamalardan bazılarını ihlal etme eğilimindedir. Ayrıca, çıkış param genellikle başarı sırasında sadece anlamlıdır. Bununla birlikte, genellikle eşzamanlılık endişeleriyle sınırlanan belirli işlemler veya performans hususları için zorunludur (örneğin, DB'ye ikinci bir gezi yapmak istemediğiniz yerlerde).

Dönüş değeri ve dış param önemsiz değilse, Scott Whitlock'un bir sonuç nesnesiyle ilgili önerisi tercih edilir (Regex'in Matchsınıfı gibi ).


7
Burada evcil hayvan peeve: outparametreleri yan etkiler konusuna tamamen diktir. Bir refparametrenin değiştirilmesi bir yan etkidir ve bir giriş parametresi üzerinden geçirdiğiniz bir nesnenin durumunu değiştirmek bir yan etkidir, ancak bir outparametre bir fonksiyonun birden fazla değer döndürmesini sağlamanın garip bir yoludur. Yan etkisi yoktur, sadece çoklu dönüş değerleri vardır.
Scott Whitlock

Dediğim eğilimindedir , çünkü insanlar bunları kullanmak nasıl. Söylediğin gibi, sadece çoklu dönüş değerleri.
Telastyn

Fakat eğer format yanlış olduğunda olayları olağanüstü bir şekilde patlatmak için parametrelerden hoşlanmazsanız ve istisnalar kullanırsanız ... formatınızın kullanıcı girişi olduğu durumu nasıl ele alırsınız? Sonra bir kullanıcı bir şeyleri havaya uçurabilir veya biri atma ve daha sonra bir istisna yakalama performans cezasına çarptırılabilir. Sağ?
Daniel AA Pelsmaeker

Ayrı bir doğrulama yöntemine sahip @ virtlink. Bunu gerek neyse onlar göndermeden önce UI uygun mesajlar sağlamaktır.
Telastyn

1
Parametreler için meşru bir örnek var ve bu, farklı türler getiren aşırı yüklere sahip bir işlev. Aşırı yük çözünürlüğü geri dönüş tipleri için işe yaramaz, ancak parametreler için olacaktır.
Robert Harvey,

2

Her zaman bir istisna atmayı tercih et. Başarısız olabilecek tüm fonksiyonlar arasında düzgün bir arayüze sahip ve başarısızlığı mümkün olduğunca gürültülü olarak gösteriyor - çok arzulanan bir özellik.

Not Parseve TryParsegerçekten arıza modları dışında aynı şey değildir. TryParseDeğeri de döndürebilen gerçeği , biraz ortogonal. Örneğin, bazı girişleri doğruladığınız durumu göz önünde bulundurun. Aslında değerin ne olduğu umrunda değil, geçerli olduğu sürece. Ve bir çeşit IsValidFor(arguments)işlev sunmanın yanlış bir yanı yok . Ancak asla birincil operasyon modu olamaz .


4
Bir yönteme yapılan çok sayıda çağrıyla uğraşıyorsanız, istisnaların performans üzerinde büyük olumsuz etkileri olabilir. İstisnalar, istisnai durumlar için ayrılmalı ve form girişini doğrulamak için mükemmel bir şekilde kabul edilebilir, ancak büyük dosyalardan sayıları ayrıştırmak için uygun olmayacaktır.
Robert Harvey,

1
Bu genel bir durum değil, daha uzman bir ihtiyaç.
DeadMG

2
Bu yüzden diyorsun. Ama "her zaman" kelimesini kullandın. :)
Robert Harvey,

@DeadMG, RobertHarvey ile hemfikirdi, ancak cevabın "çoğu zaman" yansıtacak şekilde değiştirilip değiştirilmediği ve cevabın yüksek performans gösterdiği durumlarda genel davaya istisnalar (özel amaçlı değildir) diğer seçenekleri değerlendirmek için
Gerald Davis

İstisnalar pahalı değil. Derinden atılan istisnaları yakalamak, sistemin yığını en yakın kritik noktaya çözmesi gerektiğinden pahalı olabilir. Ancak bu "pahalı" nispeten küçüktür ve sıkı iç içe döngülerde bile korkulmamalıdır.
Matthew Whited

2

Diğerlerinin de belirttiği gibi, sihirli değer (bir boolean dönüş değeri dahil), bir "aralık sonu" işareti dışında o kadar da iyi bir çözüm değildir. Sebep: Nesnenin yöntemlerini inceleseniz bile anlambilim açık değildir. Aslında tüm nesnenin tam dokümantasyonunu "ah evet, -42, bla bla bla" anlamına gelirse) aşağıya doğru okumak zorundasınız.

Bu çözüm tarihsel nedenlerden dolayı veya performans nedenleriyle kullanılabilir, ancak başka şekilde kaçınılması gerekir.

Bu iki genel durum bırakır: Sondalama veya istisnalar.

Buradaki temel kural, programın / istemeden / bir koşulu ihlal ettiği zaman işlenmesi dışında istisnalara tepki vermemesi gerektiğidir. Bunun olmamasını sağlamak için sondaj kullanılmalıdır. Bu nedenle, bir istisna ya ilgili araştırmanın önceden gerçekleştirilmediği ya da tamamen beklenmeyen bir şey olduğu anlamına gelir.

Örnek:

Belirli bir yoldan bir dosya oluşturmak istiyorsunuz.

Bu yolun dosya oluşturma veya yazma için yasal olup olmadığını önceden değerlendirmek için File nesnesini kullanmalısınız.

Programınız bir şekilde yasadışı veya başka bir şekilde yazılabilir olmayan bir yola yazmaya çalışıyorsa, bir istisna almalısınız. Bu durum bir yarış durumu nedeniyle olabilir (bazı kullanıcılar bu dizini kaldırdıktan sonra dizini kaldırdılar veya salt okunur hale getirdiler)

Beklenmeyen bir arızanın ele alınması (bir istisna ile bildirilir) ve işlemlerin önceden işlem için uygun olup olmadığının kontrol edilmesi (problama) genellikle farklı şekilde yapılandırılır ve bu nedenle farklı mekanizmalar kullanmalıdır.


0

TryKod sadece ne olduğunu gösterdiğinde , modelin en iyi seçim olduğunu düşünüyorum . Paramdan nefret ediyorum ve null olabilecek nesne gibi. Aşağıdaki sınıfı oluşturdum

public sealed class Bag<TValue>
{
    public Bag(TValue value, bool hasValue = true)
    {
        HasValue = hasValue;
        Value = value;
    }

    public static Bag<TValue> Empty
    {
        get { return new Bag<TValue>(default(TValue), false); }
    }

    public bool HasValue { get; private set; }
    public TValue Value { get; private set; }
}

bu yüzden aşağıdaki kodu yazabilirim

    public static Bag<XElement> GetXElement(this XElement element, string elementName)
    {
        try
        {
            XElement result = element.Element(elementName);
            return result == null
                       ? Bag<XElement>.Empty
                       : new Bag<XElement>(result);
        }
        catch (Exception)
        {
            return Bag<XElement>.Empty;
        }
    }

Null'a benziyor ama sadece değer türüne göre değil

Başka bir örnek

    public static Bag<string> TryParseString(this XElement element, string attributeName)
    {
        Bag<string> attributeResult = GetString(element, attributeName);
        if (attributeResult.HasValue)
        {
            return new Bag<string>(attributeResult.Value);
        }
        return Bag<string>.Empty;
    }

    private static Bag<string> GetString(XElement element, string attributeName)
    {
        try
        {
            string result = element.GetAttribute(attributeName).Value;
            return new Bag<string>(result);
        }
        catch (Exception)
        {
            return Bag<string>.Empty;
        }
    }

3
try catchGetXElement()birçok kez ararsanız ve başarısız olursanız performansınıza zarar verir .
Robert Harvey,

bazen önemli değil. Çanta çağrısına bir göz atın. Gözleminiz için teşekkürler


evet, neredeyse public struct Nullable<T> where T : structbir kısıtlamadaki temel fark. btw en son sürüm burada github.com/Nelibur/Nelibur/blob/master/Source/Nelibur.Sword/…
GSerjo

0

Eğer "sihirli değer" rotasıyla ilgileniyorsanız, bunu çözmenin bir başka yolu da Tembel sınıfın amacını aşırı yüklemektir. Tembel örnekleme ertelemek için tasarlanmış olsa da, hiçbir şey bir Belki veya Seçenek gibi kullanmanıza engel olamaz. Örneğin:

    public static Lazy<TValue> GetValue<TValue, TKey>(
        this IDictionary<TKey, TValue> dictionary,
        TKey key)
    {
        TValue retVal;
        if (dictionary.TryGetValue(key, out retVal))
        {
            var retValRef = retVal;
            var lazy = new Lazy<TValue>(() => retValRef);
            retVal = lazy.Value;
            return lazy;
        }

        return new Lazy<TValue>(() => default(TValue));
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.