dene / yakala + kullan, doğru sözdizimi


189

Hangisi:

using (var myObject = new MyClass())
{
   try
   {
      // something here...
   }
   catch(Exception ex)
   {
      // Handle exception
   }
}

VEYA

try
{
   using (var myObject = new MyClass())
   {
      // something here...
   }
}
catch(Exception ex)
{
   // Handle exception
}

7
Sadece bir not: kişi, yalnızca günlüğe kaydetme veya kaydırma haricinde , gerçekten ele alınabilen (düzeltilebilen) istisnaları yakalamaya dikkat etmelidir .
John Saunders

1
Ayrıca son unutmayın lütfen }bir usingaçıklamada istisna atabilir burada hatırlattığı gibi .
Giulio Caccin

1
İlk kod bloğunu kullanırsanız hata ayıklayıcı (VS'de) dispose yöntemini çağırmaz. Using ifadesinin kendisi bir istisna atabileceğinden finally, dispose yöntemi olarak adlandırılan zımni sağlamak için ikinci bloğu kullanmama yardımcı olur .
ShooShoSha

Yanıtlar:


98

İkincisini tercih ederim. Ayrıca nesnenin oluşturulmasıyla ilgili hataları da yakalayabilir.


11
Bu tavsiyeye katılmıyorum. Eğer bir hata oluşturması nesne oluşturma bekliyoruz, o istisna edilen işlem gerekir dışarı çık. İşlemin nereye gitmesi gerektiği hakkında bir soru varsa, beklenen istisna başka bir şey olmalıdır - beklenmedik veya beklenmeyen herhangi bir rastgele istisna yakalamayı savunmuyorsanız (klasik bir anti-desen ( işlem veya iş parçacığının İşlenmeyen Özel Durum İşleyicisi).
Jeffrey L Whitledge

1
@Jeffrey: Tarif ettiğim yaklaşım bana iyi hizmet etti ve bunu uzun zamandır yapıyorum. Hiç kimse nesne yaratmanın başarısız olmasını beklemekle ilgili bir şey söylemedi . Ancak , bir blokta potansiyel olarak başarısız olabilecek bir işlemi sararak, bir tryşey başarısız olursa bir hata mesajı açmanıza izin veren program, şimdi kullanıcıyı kurtarma ve bilgilendirme yeteneğine sahiptir.
Jonathan Wood

Yanıtınız doğru olmasına rağmen deneme / yakalama şeklindeki görüşe devam sahiptir her zaman (hemen) orada olmak.
Henk Holterman

17
Birincisi de liyakat olduğunu düşünüyorum using( DBConnection conn = DBFactory.getConnection()), bir istisna oluşması durumunda geri alınması gereken bir DB işlemi düşünün . Bana öyle geliyor ki ikisinin de yeri var.
wfoster

1
Bu aynı zamanda nesnenin atılmasıyla ilgili hataları da yakalayacaktır .
Ahmad Ibrahim

39

Bir kullanma bloğu sadece bir try / nihayet ( MSDN ) bir sözdizimi sadeleştirme olduğundan, ikinci seçeneğinizden önemli ölçüde farklı olduğundan şüphe duyuyorum, şahsen aşağıdakilerle giderdim:

MyClass myObject = null;
try {
  myObject = new MyClass();
  //important stuff
} catch (Exception ex) {
  //handle exception
} finally {
  if(myObject is IDisposable) myObject.Dispose();
}

4
Sizce bir finallyblok eklemenin usingifadeye neden tercih edilmesini düşünüyorsunuz ?
Cody Gray

10
finallyIDisposable nesnesini kullanan bir blok eklemek , usingifadenin yaptığı şeydir . Şahsen, gömülü usingblok yerine bunu beğendim, çünkü her şeyin nerede olduğunu daha net bir şekilde ifade ettiğini ve hepsinin aynı "seviyede" olduğunu düşünüyorum. Bunu birkaç gömülü usingbloktan daha çok seviyorum ... ama hepsi benim tercihim.
chezy525

8
Çok özel durum işleme uygularsanız, yazmaktan gerçekten keyif almalısınız! Bu "using" anahtar kelimesi bir süredir var ve anlamı benim için oldukça açık. Ve bunu kullanmak dağınıklığı en aza indirerek kodumun geri kalanını daha net hale getirmeye yardımcı olur.
Jonathan Wood

2
Bu yanlış. Nesne, tryifadenin içine yerleştirilebilmesi için ifadenin dışında başlatılmalıdır finally; aksi takdirde derleyici hatası verir: "Atanmamış yerel değişken 'myObject' kullanımı"
Steve Konves

3
Teknik olarak, bu da derlenmeyecek. Cannot assign null to implicitly-typed local variable;) Ama ne demek istediğini biliyorum ve kişisel olarak bunu bir blok kullanarak yerleştirmeyi tercih ederim.
Connell

20

Değişir. Windows Communication Foundation (WCF) kullanıyorsanız, deyimdeki using(...) { try... }proxy usingistisna durumdaysa düzgün çalışmaz , yani bu proxy'nin kullanılması başka bir istisnaya neden olur.

Şahsen, asgari elleçleme yaklaşımına inanıyorum, yani sadece uygulama noktasında farkında olduğunuz istisnayı ele alacağım. Başka bir deyişle, bir değişkenin başlatılmasının usingbelirli bir istisna atabileceğini biliyorsanız , onu sarıyorum try-catch. Benzer şekilde, usingvücutta değişkenle doğrudan ilgili olmayan bir şey olabilirse using, o tryistisna için başka biriyle sarıyorum. Nadiren kullanmak Exceptionbenim de catches.

Ama böyle yapmak IDisposableve usingböylece olsa belki önyargılı.


19

Catch ifadenizin bir using ifadesinde bildirilen değişkene erişmesi gerekiyorsa, içerideki tek seçenek budur.

Catch deyiminiz kullanılmadan önce kullanımda başvurulan nesneye ihtiyaç duyuyorsa, içerideki tek seçenek budur.

Catch deyiminiz, kullanıcıya bir mesaj görüntülemek gibi bilinmeyen bir süre boyunca işlem yaparsa ve kaynaklarınızı bundan önce atmak istiyorsanız, dışarıda en iyi seçeneğiniz olur.

Buna benzer bir senaryo bulduğumda, try-catch bloğu genellikle farklı bir yöntemde çağrı yığınını kullanmaktan daha yukarıdadır. Bir yöntemde, bunun içinde meydana gelen istisnaların nasıl ele alınacağını bilmek tipik değildir.

Genel tavsiyem dışarıda, dışarıda.

private void saveButton_Click(object sender, EventArgs args)
{
    try
    {
        SaveFile(myFile); // The using statement will appear somewhere in here.
    }
    catch (IOException ex)
    {
        MessageBox.Show(ex.Message);
    }
}

10

Her ikisi de geçerli sözdizimidir. Gerçekten ne yapmak istediğinize gelir: nesneyi oluşturma / atma ile ilgili hataları yakalamak istiyorsanız, ikincisini kullanın. Değilse, ilkini kullanın.


8

İlki olacak: Ben burada arayacağım tek önemli şey vardır değil çağırarak kaynaklanan herhangi istisna yakalamak MyClassyapıcı.


3

C # 8.0'dan, ikincisini aynı şekilde kullanmayı tercih ederim

public class Person : IDisposable
{
    public Person()
    {
        int a = 0;
        int b = Id / a;
    }
    public int Id { get; set; }

    public void Dispose()
    {
    }
}

ve sonra

static void Main(string[] args)
    {

        try
        {
            using var person = new Person();
        }
        catch (Exception ex) when
        (ex.TargetSite.DeclaringType.Name == nameof(Person) &&
        ex.TargetSite.MemberType == System.Reflection.MemberTypes.Constructor)
        {
            Debug.Write("Error Constructor Person");
        }
        catch (Exception ex) when
       (ex.TargetSite.DeclaringType.Name == nameof(Person) &&
       ex.TargetSite.MemberType != System.Reflection.MemberTypes.Constructor)
        {
            Debug.Write("Error Person");
        }
        catch (Exception ex)
        {
            Debug.Write(ex.Message);
        }
        finally
        {
            Debug.Write("finally");
        }
    }

1

Using () bloğunda başlattığınız nesne herhangi bir istisna fırlatabilirse, ikinci sözdizimini kullanmalısınız, aksi takdirde her ikisi de eşit derecede geçerlidir.

Senaryomda, bir dosyayı açmak zorunda kaldım ve Using () bloğunda başlattığım nesnenin yapıcısında filePath geçiriyordum ve filePath yanlış / boşsa istisna atabilir. Bu durumda, ikinci sözdizimi mantıklıdır.

Örnek kodum: -

try
{
    using (var obj= new MyClass("fileName.extension"))
    {

    }
}
catch(Exception ex)
{
     //Take actions according to the exception.
}

1

C # 8.0'dan itibaren using, iç içe bloktan kurtulmak için bazı koşullar altında ifadeleri basitleştirebilirsiniz ve daha sonra sadece kapalı blok için geçerlidir.

Böylece iki örneğiniz aşağıdakilere indirgenebilir:

using var myObject = new MyClass();
try
{
   // something here...
}
catch(Exception ex)
{
   // Handle exception
}

Ve:

try
{
   using var myObject = new MyClass();
   // something here...
}
catch(Exception ex)
{
   // Handle exception
}

İkisi de oldukça açık; ve sonra bu ikisi arasındaki seçimi, nesnenin kapsamının ne olmasını istediğiniz, örnekleme hatalarını işlemek istediğiniz yerde ve ne zaman atmak istediğinize bağlıdır.

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.