C # 'da Java tarzı anahtar kelime atma nasıl kullanılır?


91

Java'da throwsanahtar kelime, bir yöntemin kendi başına bir istisnayı işlemeyeceğini, bunun yerine onu çağırma yöntemine atacağını bildirmesine izin verir.

C # 'da benzer bir anahtar kelime / özellik var mı?

Eşdeğeri yoksa, aynı (veya benzer) etkiyi nasıl elde edebilirsiniz?

Yanıtlar:


78

Java'da, bir istisnayı işlemeniz veya yöntemi throwsanahtar sözcüğü kullanarak onu atabilecek bir yöntem olarak işaretlemeniz gerekir .

C #, bu anahtar kelimeye veya C # 'da olduğu gibi eşdeğer bir anahtar kelimeye sahip değildir, eğer bir istisnayı işlemezseniz, yakalanana kadar kabarcıklar oluşur veya yakalanmazsa programı sonlandırır.

Bunu halletmek istiyorsanız, tekrar fırlatın, aşağıdakileri yapabilirsiniz:

try
{
  // code that throws an exception
}
catch(ArgumentNullException ex)
{
  // code that handles the exception
  throw;
}

1
"kabaracak", bu, bunun Java'da bir throws cümlesine sahip tüm yöntemlere eşdeğer olduğu anlamına mı geliyor?
Louis Rhys

1
@Louis RH - tür. Bu, bir istisnanın ele alınmadığı takdirde, ele alınana kadar her bir arama işlevi boyunca arama zincirinde yukarı çıkacağı anlamına gelir.
Oded

1
@Louis RH tam olarak değil, bu kodu derlemek için en azından Ana İstisnayı yakalamanız gerektiği anlamına gelir. C # kontrol edilen istisnaları bilmediğinden, onları yakalamak size kalmıştır, aksi takdirde sadece çalışma zamanına iner ve kodunuzu keser.
Johannes Wachter

1
@jwatcher: Bir ana yöntemin de bir fırlatma cümlesi olabilir.
Louis Rhys

4
@AshishKamble - eh. Fikir meselesi. Özel durum işleme .NET'te farklıdır . Neyin "daha iyi" olduğunu bildiğinizi varsaymayın.
Oded

109

Operasyon , Java'nın throwscümlesinin C # eşdeğerini soruyor - throwanahtar kelimeyi değil . Bu, kontrol edilen bir istisnanın atılabileceğini belirtmek için Java'daki yöntem imzalarında kullanılır.

C # 'da, Java kontrollü bir istisnanın doğrudan eşdeğeri yoktur. C # 'ın eşdeğer bir yöntem imza cümlesi yoktur.

// Java - need to have throws clause if IOException not handled
public void readFile() throws java.io.IOException {
  ...not explicitly handling java.io.IOException...
}

Çevirir

// C# - no equivalent of throws clause exceptions are unchecked
public void ReadFile() 
{
  ...not explicitly handling System.IO.IOException...
}

30

Evet bu eski bir konu, ancak cevapları aradığımda sık sık eski konuları buluyorum, bu yüzden bulduğum yararlı bir şey ekleyeceğimi düşündüm.

Visual Studio 2012 kullanıyorsanız, bir IDE düzeyi eşdeğeri "atma" sağlamak için kullanılabilecek yerleşik bir araç vardır.

Eğer kullanırsanız XML Belgeleri Yorumlar , yukarıda da belirtildiği gibi, o zaman kullanabilirsiniz <istisna> neden atıldığında ya yanı sıra bilgi yöntemiyle veya sınıf tarafından atılan istisna tipini belirtmek için etiketini.

misal:

    /// <summary>This method throws an exception.</summary>
    /// <param name="myPath">A path to a directory that will be zipped.</param>
    /// <exception cref="IOException">This exception is thrown if the archive already exists</exception>
    public void FooThrowsAnException (string myPath)
    {
        // This will throw an IO exception
        ZipFile.CreateFromDirectory(myPath);
    }

4
OP, bu senin cevabın. Tahmin ediyorum, ancak JAVA'nın throwsgeliştiriciye bilgilendirici olmasının yanı sıra çalışma zamanı için muhtemelen hiçbir şey ifade etmiyor. Aynı şekilde, @mvanella'nın burada işaret ettiği şey, C # 'ın tam olarak aynısını yapmanın yolu. Bu "xml dokümantasyonunun" daha önemli bir amacı olduğunu zaten bildiğinizi varsayıyorum. Bu ileti dizisinin eski olduğunu biliyorum.
Hari Lubovac

Aslında Java, bir throwscümlede açıkça belirtilmediği veya bir throwkomutla atılmadığı sürece istisnaları ortaya çıkarmaz . Bu, bir RunTimeException meydana gelirse ve meydana geldiği aynı yöntemde işlenmezse, yürütme orada durur anlamına gelir.
Pedro Lima

18

İşte az önce bytes.com'da bulduğum benzer bir sorunun cevabı :

Kısa cevap hayır. C # 'da kontrol edilen istisna yoktur. Dilin tasarımcısı bu röportajda bu kararı tartışıyor:

http://www.artima.com/intv/handcuffs.html

Size en yakın olan şey, XML belgelerinizdeki etiketleri kullanmak ve NDoc tarafından oluşturulan belgeleri kodunuzla / derlemelerinizle birlikte dağıtmaktır, böylece diğer insanlar hangi istisnaları attığınızı görebilir (MS, MSDN belgelerinde tam olarak budur). Derleyicinin size işlenmemiş istisnaları söylemesi için güvenemezsiniz, ancak java'da alışkın olduğunuz gibi.


7

Buradaki yanıtların çoğunu inceledikten sonra, birkaç fikir eklemek istiyorum.

  1. XML Belgeleme Yorumlarına güvenmek ve başkalarının da güvenmesini beklemek kötü bir seçimdir. Karşılaştığım çoğu C # kodu, yöntemleri tamamen ve tutarlı bir şekilde XML Belgeleme Yorumları ile belgelemiyor. Ve daha büyük bir sorun var ki, C # 'da kontrol edilen istisnalar olmadan, API kullanıcınızın hepsini tek tek nasıl ele alacağını bilmek amacıyla yönteminizin attığı tüm istisnaları nasıl belgeleyebilirsiniz? Unutmayın, yalnızca uygulamanızda throw anahtar kelimesi ile kendinizi attığınız kişileri bilirsiniz. Yöntem uygulamanızın içinde kullandığınız API'ler, belgelenmemiş olabileceğinden ve bunları uygulamanızda kullanmadığınız için bilmediğiniz istisnaları da atabilir, bu nedenle bunlar, sizi arayan kişinin karşısında patlayacaktır. yöntem. Diğer bir deyişle,

  2. Andreas, C # tasarım ekibinin neden kontrol edilen istisnalara karşı karar verdiğine dair yanıtlarda Anders Hejlsberg ile bir röportaj yaptı. Orijinal soruya verilecek nihai yanıt, bu röportajda gizli:

Programcılar, her yerde try nihayet yazarak kodlarını korurlar, böylece bir istisna olursa doğru şekilde geri dönerler, ancak istisnaları ele almakla aslında ilgilenmezler.

Diğer bir deyişle, her zaman hepsini her yerde yakalayacağınız için, hiç kimse belirli bir API için ne tür bir istisnanın beklenebileceğiyle ilgilenmemelidir. Ve belirli istisnaları gerçekten önemsemek istiyorsanız, bunların nasıl ele alınacağı size bağlıdır ve Java atar anahtar kelimesi gibi bir şeyle bir yöntem imzası tanımlayan biri değil, bir API kullanıcısında belirli istisna işlemlerini zorlar.

-

Şahsen ben burada parçalandım. İstisnaları kontrol etmenin sorunu yeni, farklı sorunlar eklemeden çözmediği konusunda Anders'e katılıyorum. Tıpkı XML dokümantasyon yorumlarında olduğu gibi, her şeyin try nihayet bloklarına sarılı olduğu C # kodunu nadiren görüyorum. Bana öyle geliyor ki bu gerçekten tek seçeneğiniz ve iyi bir uygulama gibi görünen bir şey.


3

Aslında C # 'da istisnaları kontrol etmemek iyi veya kötü bir şey olarak kabul edilebilir.

Kontrol edilen istisnalar size aşağıdaki sorunları sağladığından, bunun iyi bir çözüm olduğunu düşünüyorum:

  1. İşletme / etki alanı katmanına sızan Teknik İstisnalar, çünkü bunları düşük düzeyde düzgün bir şekilde işleyemezsiniz.
  2. API tasarımıyla her zaman iyi oynamayan yöntem imzasına aittirler.

Bundan dolayı, daha büyük uygulamaların çoğunda kontrol edildiğinde aşağıdaki kalıbı sıklıkla göreceksiniz İstisnalar oluşur:

try {
    // Some Code
} catch(SomeException ex){
    throw new RuntimeException(ex);
}

Bu, esasen C # /. NET'in tüm İstisnaları işleme şeklini taklit etmek anlamına gelir.


Kontrol edilen istisnaların lambdalarla nasıl karışacağını hayal edemiyorum!
Gabe

@Gabe: Eminim onları karıştırmanıza izin veren bir konsept bulmuşsunuzdur, ancak dediğim gibi, kontrol edilen istisnalar Java'da da çoğunlukla iyi bir uygulama değil, özellikle daha karmaşık uygulamalarda. Bu yüzden C # 'da orada olmamaları iyi.
Johannes Wachter

3

Bunu soruyorsunuz:

Bir İstisnayı Yeniden Atmak

public void Method()
{
  try
  {
      int x = 0;
      int sum = 100/x;
  }
  catch(DivideByZeroException e)
  {
      throw;
  }
}

veya

static void Main() 
    {
        string s = null;

        if (s == null) 
        {
            throw new ArgumentNullException();
        }

        Console.Write("The string s is null"); // not executed
    }

3
Kullanmak için +1 throw. Bunu kullanarak yığın izleme kaybolmaz.
Giuseppe Accaputo

2

.Net CodeContract EnsuresOnThrow<>ve java throwstanımlayıcı arasında bazı kısa süreli benzerlikler vardır, çünkü her ikisi de arayana bir işlev veya yöntemden ortaya çıkabilecek istisna türü olarak sinyal verebilir, ancak 2 arasında büyük farklılıklar da vardır:

  • EnsuresOnThrow<>sadece hangi istisnaların atılabileceğini belirtmenin ötesine geçer, aynı zamanda atılmalarının garanti edildiği koşulları da şart koşar - bu, istisna koşulunun tanımlanması önemsiz değilse, çağrılan yöntemde oldukça zahmetli bir kod olabilir. Java throws, hangi istisnaların atılabileceğine dair bir gösterge sağlar (örn. IMO, .Net'teki odak, bunu kanıtlamak için sözleşme yapan yöntemin içindedir throw, oysa Java'da odak, istisna olasılığını kabul etmek için arayan kişiye geçer).
  • .Net CC, Java'nın sahip olduğu Kontrol Edilmiş ve Kontrol Edilmemiş istisnaları arasında ayrım yapmaz , ancak CC kılavuz bölümü 2.2.2'de

"istisnai son koşulları yalnızca arayan kişinin API'nin parçası olarak beklemesi gereken istisnalar için kullanın"

  • .Net'te arayan, istisna ile herhangi bir şey yapıp yapmayacağını belirleyebilir (örneğin, sözleşmeleri devre dışı bırakarak). Java'da arayan , arayüzüne aynı istisna için bir eklese bile bir şeyler yapmalıdırthrows .

Kod Sözleşmeleri kılavuzu burada


0

C # yönteminin amacı yalnızca bir istisna atmaksa (js dönüş türünün söylediği gibi) bu istisnayı döndürmenizi öneririm. Aşağıdaki örneğe bakın:

    public EntityNotFoundException GetEntityNotFoundException(Type entityType, object id)
    {
        return new EntityNotFoundException($"The object '{entityType.Name}' with given id '{id}' not found.");
    }

    public TEntity GetEntity<TEntity>(string id)
    {
        var entity = session.Get<TEntity>(id);
        if (entity == null)
            throw GetEntityNotFoundException(typeof(TEntity), id);
        return entity;
    }


-1

Merak edenler için, bir sonraki yönteme geçmek için neyi yakaladığınızı tanımlamanıza bile gerek yok. Tüm hata işlemlerinizi tek bir ana iş parçacığında istiyorsanız, her şeyi yakalayabilir ve şu şekilde iletebilirsiniz:

try {
    //your code here
}
catch {
    //this will throw any exceptions caught by this try/catch
    throw;
}

Lütfen biraz cevap düzenlemesi yapın. Yanlışlıkla -1'i tıkladım. Siz herhangi bir değişiklik yapana kadar onu çıkaramam.
proximab
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.