arasındaki fark nedir
try { ... }
catch{ throw }
ve
try{ ... }
catch(Exception e) {throw new Exception(e.message) }
Ne olursa olsun ikinci bir mesaj gösterir?
arasındaki fark nedir
try { ... }
catch{ throw }
ve
try{ ... }
catch(Exception e) {throw new Exception(e.message) }
Ne olursa olsun ikinci bir mesaj gösterir?
Yanıtlar:
throw; orijinal istisnayı yeniden oluşturur ve orijinal yığın izini korur.
throw ex;orijinal istisnayı atar ancak catchbloğunuza kadar tüm yığın izleme bilgilerini yok ederek yığın izlemesini sıfırlar .
throw ex;throw new Exception(ex.Message);daha da kötüdür. Exceptionİstisnanın orijinal yığın izini ve türünü kaybeden yepyeni bir örnek oluşturur . (ör IOException.).
Ayrıca, bazı istisnalar ek bilgiler içerir (ör ArgumentException.ParamName.).
throw new Exception(ex.Message); bu bilgiyi de yok edecektir.
Belirli durumlarda, özel bir istisna nesnesindeki tüm istisnaları sarmak isteyebilirsiniz, böylece istisna atıldığında kodun ne yaptığı hakkında ek bilgi sağlayabilirsiniz.
Bunu yapmak için, miras alan yeni bir sınıf tanımlayın Exception, dört istisna kurucusunun tümünü ve isteğe bağlı InnerExceptionolarak ek bilgilerin yanı sıra ek bilgi alan bir kurucu ekleyin ve parametre olarak ileterekexInnerException yeni istisna sınıfınızı atın . Orijinali ileterek InnerException, yığın izlemesi de dahil olmak üzere orijinal istisnanın tüm özelliklerini korursunuz.
throw new MyCustomException(myMessage, ex);Tabii ki olmalı .
ex.Messageki, bir daha kötüsü.
[Serializable()].
throw;durumun oluştuğu gerçek satır numarası yerine satır numarası gelir throw;. Bunu nasıl ele almayı önerirsiniz? stackoverflow.com/questions/2493779/…
Birincisi orijinal yığın izini korur:
try { ... }
catch
{
// Do something.
throw;
}
İkincisi, istisnanın türünü ve / veya mesaj ve diğer verileri değiştirmenizi sağlar:
try { ... } catch (Exception e)
{
throw new BarException("Something broke!");
}
İçsel bir istisnayı geçmenin üçüncü bir yolu da vardır:
try { ... }
catch (FooException e) {
throw new BarException("foo", e);
}
Şunu kullanmanızı öneririm:
Kimsenin görmediği bir nokta daha var:
Yakalama {} bloğunuzda hiçbir şey yapmazsanız, bir deneme ... yakalama anlamsızdır. Bunu her zaman görüyorum:
try
{
//Code here
}
catch
{
throw;
}
Veya daha kötüsü:
try
{
//Code here
}
catch(Exception ex)
{
throw ex;
}
En kötüsü:
try
{
//Code here
}
catch(Exception ex)
{
throw new System.Exception(ex.Message);
}
throwyakalanan kural dışı durumun throw new Exceptionbazı ayrıntılarını kaybederken , yığın izini koruyarak yakalanan kural dışı durumu yeniden atar .
Normalde, throwbir istisnayı o noktada tam olarak işlemeden kendi başına kaydetmek için kullanırsınız .
BlackWasp, C # 'da Özel Durumlar Atma başlıklı yeterince iyi bir makaleye sahiptir .
Yeni bir İstisna atmak mevcut yığın izini uçurur.
throw;orijinal yığın izini korur ve neredeyse her zaman daha kullanışlıdır. Bu kuralın istisnası, İstisnayı kendi özel bir İstisnasına sarmak istediğiniz zamandır. Daha sonra şunları yapmalısınız:
catch(Exception e)
{
throw new CustomException(customMessage, e);
}
throwyakalanan bir istisnayı yeniden düzenlemek içindir. Bu, çağrı zincirini geçmeden önce istisna ile bir şeyler yapmak istiyorsanız yararlı olabilir.
throwBağımsız değişken olmadan kullanmak , çağrı yığınını hata ayıklama amacıyla korur.
İkinci örneğiniz, istisnanın yığın izlemesini sıfırlayacaktır. Birincisi, istisnanın kökenlerini en doğru şekilde korur. Ayrıca, aslında neyin yanlış gittiğini bilmenin anahtarı olan orijinal türü açtınız ... İkincisi işlevsellik için gerekiyorsa - örneğin, genişletilmiş bilgi eklemek veya özel bir 'HandleableException' gibi özel bir türle yeniden sarmak için InnerException özelliğinin de ayarlandığından emin olun!
En önemli fark, ikinci ifadenin istisna türünü silmesidir. İstisna türü, istisnaları yakalamada hayati bir rol oynar:
public void MyMethod ()
{
// both can throw IOException
try { foo(); } catch { throw; }
try { bar(); } catch(E) {throw new Exception(E.message); }
}
(...)
try {
MyMethod ();
} catch (IOException ex) {
Console.WriteLine ("Error with I/O"); // [1]
} catch (Exception ex) {
Console.WriteLine ("Other error"); // [2]
}
Eğer foo()atar IOException, [1]catch bloğu özel durum yakalayacak. Ama bar()fırlattığında IOException, düz Exceptionkarıncaya dönüştürülecek [1]catch bloğu tarafından yakalanmayacak.
atmak veya atmak, her ikisi de istisnayı atmak veya yeniden atmak için kullanılır, sadece hata bilgilerini günlüğe kaydettiğinizde ve herhangi bir bilgiyi arayan kişiye geri göndermek istemediğinizde, hatayı yakala ve bırak olarak kaydedersiniz. Ancak, atma veya atma kullandığınız arayan kişiye istisna hakkında bazı anlamlı bilgiler göndermek istiyorsanız. Şimdi atma ve atma arasındaki fark, atmanın yığın izini ve diğer bilgileri koruduğu, ancak ex'in yeni bir istisna nesnesi oluşturduğu ve dolayısıyla orijinal yığın izlemesinin kaybolmasıdır. Bu nedenle, atma ve atma e'yi ne zaman kullanmalıyız? Çağrı yığını bilgisini sıfırlamak gibi bir istisnayı yeniden yazmak isteyebileceğiniz birkaç durum var. Örneğin, yöntem bir kitaplıktaysa ve kitaplığın ayrıntılarını arama kodundan gizlemek istiyorsanız, çağrı yığınının kitaplıktaki özel yöntemler hakkında bilgi içermesini istemezsiniz. Bu durumda, kütüphanenin genel yöntemlerinde istisnalar yakalayabilir ve ardından çağrı yığını bu genel yöntemlerde başlayacak şekilde bunları yeniden oluşturabilirsiniz.
Buradaki cevapların hiçbiri, farkı anlamaya çalışan insanlar için yararlı olabilecek farkı göstermiyor. Bu örnek kodu düşünün:
using System;
using System.Collections.Generic;
namespace ExceptionDemo
{
class Program
{
static void Main(string[] args)
{
void fail()
{
(null as string).Trim();
}
void bareThrow()
{
try
{
fail();
}
catch (Exception e)
{
throw;
}
}
void rethrow()
{
try
{
fail();
}
catch (Exception e)
{
throw e;
}
}
void innerThrow()
{
try
{
fail();
}
catch (Exception e)
{
throw new Exception("outer", e);
}
}
var cases = new Dictionary<string, Action>()
{
{ "Bare Throw:", bareThrow },
{ "Rethrow", rethrow },
{ "Inner Throw", innerThrow }
};
foreach (var c in cases)
{
Console.WriteLine(c.Key);
Console.WriteLine(new string('-', 40));
try
{
c.Value();
} catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
}
Hangi aşağıdaki çıktıyı üretir:
Bare Throw:
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
at ExceptionDemo.Program.<>c.<Main>g__bareThrow|0_1() in C:\...\ExceptionDemo\Program.cs:line 19
at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64
Rethrow
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
at ExceptionDemo.Program.<>c.<Main>g__rethrow|0_2() in C:\...\ExceptionDemo\Program.cs:line 35
at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64
Inner Throw
----------------------------------------
System.Exception: outer ---> System.NullReferenceException: Object reference not set to an instance of an object.
at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 43
--- End of inner exception stack trace ---
at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 47
at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64
Önceki cevaplarda belirtildiği gibi çıplak atma, hem başarısız olan orijinal kod satırını (satır 12) hem de istisna oluştuğunda çağrı yığınında aktif olan diğer iki noktayı (satır 19 ve 64) açıkça gösterir.
Yeniden atma kasasının çıktısı bunun neden bir sorun olduğunu gösterir. Kural dışı durum bu şekilde yeniden oluşturulduğunda kural dışı durum orijinal yığın bilgilerini içermez. Yalnızca throw e(hat 35) ve en dıştaki çağrı yığın noktasının (hat 64) dahil edildiğine dikkat edin. İstisnaları bu şekilde atarsanız, fail () yöntemini sorunun kaynağı olarak izlemek zor olacaktır.
Son durum (innerThrow) en ayrıntılı olanıdır ve yukarıdakilerden herhangi birinden daha fazla bilgi içerir. Yeni bir istisna oluşturduğumuzdan, içeriğe dayalı bilgiler ("dış" mesajı ekleyebiliyoruz, ancak burada yeni istisnada .Data sözlüğüne ekleyebiliriz) ve aynı zamanda orijinaldeki tüm bilgileri koruyabiliriz istisna (yardım bağlantıları, veri sözlüğü vb. dahil).