“Try” ne zaman C # yöntem adlarında kullanılmalıdır?


180

İş arkadaşlarımızla, yöntem adı "Dene" ile başlıyorsa bunun ne anlama geldiğini tartışıyorduk.

Aşağıdaki görüşler vardı:

  • Yöntem null değer döndürebildiğinde "Dene" seçeneğini kullanın.
  • Yöntem bir istisna atmayacaksa "Dene" yi kullanın.

Resmi tanım nedir? Yöntem adında "Dene" ne diyor? Bununla ilgili resmi bir kılavuz var mı?


83
+1 Bu kadar düşüncelerini işlevlerinin adlarına koyan insanlar aslında "bir sonraki adamı" arıyorlar. Bunun neden yakın oy aldığından emin değilim (ve bu gece çok fazla oy alan bir adamdan geliyor .)
Jonathon Reinhart

7
@JonathonReinhart, yakın oy aldı çünkü "Şu anda olduğu gibi, bu soru Soru-Cevap biçimimiz için iyi bir uyum değil. Yanıtların gerçekler, referanslar veya belirli bir uzmanlık tarafından desteklenmesini bekliyoruz, ancak bu soru muhtemelen tartışma, argümanlar isteyecektir , oylama veya genişletilmiş tartışma. "
Pranav Hosangadi

16
Orada olan (benim cevap bakınız) sorusunu yanıtlar Microsoft tarafından resmi bir açıklama. Bu nasıl bir gerçek değil?
Erik Schierboom

6
@PranavHosangadi, Erik'in belirttiği gibi, gerçekler tarafından desteklenmektedir. Ayrıca, burada geçerli bir cevap vermek için özel uzmanlığa sahip çok deneyimli C # geliştiricileri vardır . Cehennem, Eric Lippert C # dilinin baş mimarı. Bence o özel uzmanlık diyebilirsiniz .
Jonathon Reinhart

4
@ErikSchierboom MS kılavuzunun gerçek olduğu gerçeğidir. MS kılavuzunun kullanılacak doğru kılavuz olması öznel ve tartışmalıdır.
Servi

Yanıtlar:


148

Bu TryParse deseni olarak bilinir ve Microsoft tarafından belgelenmiştir. Resmi İstisnalar ve Performans MSDN sayfada şunlar :

İstisnalarla ilgili performans sorunlarından kaçınmak için ortak senaryolarda istisnalar atabilecek üyeler için TryParse şablonunu göz önünde bulundurun.

Bu nedenle, düzenli kullanım durumunun bir istisna (int ayrıştırma gibi) atabileceği anlamına gelen bir kodunuz varsa, TryParse şablonu mantıklıdır.


2
Bu modeli belgeleyen başka bir yararlı bağlantı (TryParse için arama yapın) blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
Vivek Maharajh

2
Temel olarak, bir TryParse yönteminiz varsa, TryParse yanlış döndürdüğünde atanan bir Parse yönteminiz olmalıdır. Tersine, bir Ayrıştırma yönteminiz varsa, Ayrıştırma attığında yanlış dönen bir TryParse yöntemine sahip olmalısınız
3Doubloons

5
+1. Buna ek olarak, istisnalar genellikle "istisnai" durumlar içindir. Kolayca başarısız olabilecek bir şey yapıyorsanız ve bu başarısızlık özellikle dikkate değer değilse, bu kalıbı kullanmak bir deneme / yakalamadan daha deyimseldir
Adam Robinson

Böyle bir model gerçekten Microsoft'tan yönergeler gerektirdi mi? Oldukça basit şeyler gibi görünüyor.
Dave Lawrence

19
Bu ise temel şeyler, ama o kurallar kullanışlı değildir anlamına gelmez. Platformu yeterince iyi bilmiyorsanız, temel şeyleri doğru yapmak oldukça zor olabilir.
Erik Schierboom

119

(Düzeltildi) Erik'in önerdiği gibi resmi bir kılavuz var.

Ben gördüğümde TrySomethingyöntemi, bunu farz

  • atmaz
  • İadeler bool
  • değer bekliyorsam, 'out' parametresi ile döndürülür
  • Somethingherhangi bir istisnayı kendim halletmeme izin veren bir yöntem var . (düzenle, Jesse Webb tarafından önerildi)

4
Düzeltme - Resmi yönergeleri vardır. Erik'in cevabına bakın.
nothrow

8
+1 Ancak 4. beklentim var: Bir TryFooyöntem varsa, Foo`` istisnaları kendim halletmeme izin veren benzer bir yöntem olacak . Bu yöntemlerin imzaları muhtemelen farklı olacaktır, bu nedenle kullanımları diğer kod değişiklikleri olmadan değiştirilemez.
Jesse Webb

1
@ JesseWebb, bunu belirttiğin için teşekkürler. Sakıncası yoksa, cevabımı yorumuma ekledim.
nothrow

1
"Atmaz" bana aşırı genelleşmiş gibi geliyor. Örneğin, int32.TryParse (String, NumberStyles, IFormatProvider, Int32), style parametresini beğenmezse ArgumentException özel durumunu atar.
Jirka Hanika

"Atmama" nın aşırı genelleştirilebileceğini kabul ediyorum, ancak niyetin parametrelerin değerinden ziyade yürütme sonucu atmadığını iletmek olduğuna inanıyorum.
ConfusingBoat

8

tryDevam etmek istediğinizde kullanmanız gerektiğini düşünüyorum . Bir yöntemin bir değer döndürüp döndürmemesi önemli değildir.

Durum 1: iyi dönerse, bir şekilde devam edebilirsiniz.

Durum 2: dönmüyorsa: hala iyidir; başka bir yoldan ilerleyebilirsiniz.

Bu yöntemin çıktısı olarak bir değer bekliyorsanız, outparametreyi kullanın .

Misal

int value
if (dictionary.TryGetValue("key", out value))
{
    // Proceed in some way
}
else
{
    // Proceed in some other way
}

6

Yöntem çağrısının geçerli olmayan sonuç üretebileceğini göstermek istediğinizde, yöntem adında "Dene" yi kullanmanız gerekir. .NET standardını izleyerek, bu arada, bir istisna oluşturan bir işlev değil, bazılarını döndüren VALIDveyaNON_VALID programa uygunluk açısından, bir değer.

Sonunda, tüm bunlar grubunuzda kullanmaya karar verdiğiniz adlandırma kuralıyla ilgilidir.


5

tryAşağıdaki durumlarda yöntem adınıza eklediğinizden emin olun :

  • istisna atmıyorsun
  • yönteminizin aşağıdaki imzası vardır: bool TrySomething(input, out yourReturn)

Temel olarak try-methods kullanırsak, sadece boolean bir sonuç alırız.

Bu nedenle, aşağıdaki kod herhangi bir istisna atmayacaktır:

string input = "blabla";
int number;
if (int.TryParse(input, out number))
{
// wooohooo we got an int!
} else
{
//dooh!
}

Bu kod istisnalar getirebilir (ve bu durumda):

string input = "blabla";
int number;
try
{
     number = int.Parse(input); //throws an exception
}
catch (Exception)
{
     //dooh!
}

Try yöntemlerini kullanmak kodlamanın daha güvenli ve daha savunmacı bir yoludur. Ayrıca kod pasajı # 2, bir tamsayı değilse yürütmek için daha fazla performans gerektirir.


Kod snippet'iniz # 2 int number = int.Parse(input);, bu bağlamda daha anlamlı olmasını istiyorsanız okumalıdır .
Pierre Arnaud

@PierreArnaud Teşekkürler, değiştirdim!
Fabian Bigler

int number;Deneme bloğundan ve number = ...atamadan önce bildirimi hala kaçırıyorsunuz .
Pierre Arnaud

@PierreArnaud Teşekkürler, şimdi 'int number' da ekledim.
Fabian Bigler

İstisna, TryLoadFile(path, out file)woah gibi gerçekleştirilen doğrudan eylemle biraz ilgili değilse, RAM dışında da istisnalar atabileceğinizi unutmayın . Bu yüzden arayan, kötü bir yol veya erişim reddedildi için hiçbir hata beklemez, ancak yanlış giden whackier şeyler için bir istisna oluşturur. Ve belgeleyin.
Luke Puplett

0

Bob Amca, Clean Code adlı kitabında aşağıdaki örneği veriyor . Bir istisnanın atılmasını beklediğimizde, Trybir yöntem adı önekini kullanabiliriz :

public void sendShutDown()
{
    try{
        tryToShutDown();
    } catch (DeviceShutDownError e) {
        logger.log(e);            
    }
}

Ve sonra (uyarlandı):

private void tryToShutDown()
{
    //some code with no error handling, but
    //something might go wrong here
}

tryToShutDownBunun sorumluluğu çünkü yöntem, herhangi bir hata işleme yapmaz sendShutDownyöntemle.

TryParseMicrosoft desen biz çıkış parametrelerini önlemek gerektiğini söylüyor temiz kod kılavuzunu ihlal.

C # 'ın yeni bir sürümünü geliştirmiyorsak, tüm Microsoft yönergelerine bağlı kalmak zorunda değiliz. Bazen en iyisi değiller.

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.