Bagaimana cara menggunakan kata kunci melempar gaya Java di C #?

91

Di Java, throwskata kunci memungkinkan metode untuk mendeklarasikan bahwa ia tidak akan menangani pengecualiannya sendiri, tetapi membuangnya ke metode pemanggilan.

Apakah ada kata kunci / atribut yang serupa di C #?

Jika tidak ada padanan, bagaimana Anda bisa mencapai efek yang sama (atau serupa)?

Louis Rhys
sumber

Jawaban:

78

Di Java, Anda harus menangani pengecualian atau menandai metode tersebut sebagai salah satu metode yang mungkin membuangnya menggunakan throwskata kunci.

C # tidak memiliki kata kunci ini atau kata kunci yang setara, seperti di C #, jika Anda tidak menangani pengecualian, itu akan menggelembung, sampai tertangkap atau jika tidak tertangkap itu akan menghentikan program.

Jika Anda ingin menanganinya maka lemparan ulang Anda dapat melakukan hal berikut:

try
{
  // code that throws an exception
}
catch(ArgumentNullException ex)
{
  // code that handles the exception
  throw;
}
Oded
sumber
1
"itu akan menggelembung", apakah ini berarti bahwa ini setara dengan semua metode yang memiliki klausul lemparan di Jawa?
Louis Rhys
1
@Louis RH - semacam. Artinya pengecualian, jika tidak ditangani, akan naik rantai panggilan melalui setiap fungsi panggilan sampai ditangani.
Oded
1
@Louis RH tidak sepenuhnya, itu berarti Anda harus menangkap Exception setidaknya di Anda Utama untuk mengkompilasi kode. Karena C # tidak mengetahui pengecualian yang dicentang, terserah Anda untuk menangkapnya jika tidak, mereka hanya akan mendarat di runtime dan mengganggu kode Anda.
Johannes Wachter
1
@jwatcher: metode utama juga dapat memiliki klausa lemparan.
Louis Rhys
4
@AshishKamble - eh. Soal opini. Penanganan pengecualian berbeda di .NET. Jangan berasumsi Anda tahu apa yang "lebih baik".
Oded
108

Operasi menanyakan tentang C # yang setara dengan throwsklausa Java - bukan throwkata kunci. Ini digunakan dalam tanda tangan metode di Java untuk menunjukkan pengecualian yang dicentang dapat dilemparkan.

Di C #, tidak ada padanan langsung dari pengecualian yang dicentang Java. C # tidak memiliki klausul tanda tangan metode yang setara.

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

diterjemahkan menjadi

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

Ya, ini adalah utas lama, namun saya sering menemukan utas lama ketika saya mencari jawaban di Google jadi saya pikir saya akan menambahkan sesuatu yang bermanfaat yang saya temukan.

Jika Anda menggunakan Visual Studio 2012 ada alat bawaan yang dapat digunakan untuk memungkinkan tingkat IDE "melempar" setara.

Jika Anda menggunakan Komentar Dokumentasi XML , seperti yang disebutkan di atas, Anda dapat menggunakan tag <exception> untuk menentukan jenis pengecualian yang dilemparkan oleh metode atau kelas serta informasi tentang kapan atau mengapa itu dilemparkan.

contoh:

    /// <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);
    }
mvanella
sumber
4
OP, ini jawaban Anda. Saya menebak, tapi throwskemungkinan JAVA tidak berarti apa-apa bagi runtime, selain informatif bagi pengembang. Demikian juga, apa yang @mvanella tunjukkan di sini adalah cara C # untuk melakukan hal yang sama. Saya berasumsi Anda sudah tahu bahwa "dokumentasi xml" ini memiliki tujuan yang lebih signifikan. Saya tahu utas ini sudah tua.
Hari Lubovac
Sebenarnya, Java tidak memunculkan pengecualian kecuali jika ditentukan secara eksplisit dalam throwsklausa atau dilemparkan oleh throwperintah. Itu berarti jika RunTimeException terjadi dan tidak ditangani dalam metode yang sama di mana ia terjadi, eksekusi akan berhenti di situ.
Pedro Lima
18

Berikut adalah jawaban untuk pertanyaan serupa yang baru saya temukan di bytes.com :

Jawaban singkatnya tidak. Tidak ada pengecualian di C #. Perancang bahasa membahas keputusan ini dalam wawancara ini:

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

Hal terdekat yang bisa Anda dapatkan adalah dengan menggunakan tag dalam dokumentasi XML Anda, dan mendistribusikan dokumen yang dibuat NDoc dengan kode / rakitan Anda sehingga orang lain dapat melihat pengecualian mana yang Anda berikan (yang persis seperti yang dilakukan MS dalam dokumentasi MSDN). Anda tidak dapat mengandalkan kompilator untuk memberi tahu Anda tentang pengecualian yang tidak tertangani, seperti yang mungkin biasa Anda lakukan di java.

Andreas Dolk
sumber
7

Setelah melalui sebagian besar jawaban di sini, saya ingin menambahkan beberapa pemikiran.

  1. Mengandalkan Komentar Dokumentasi XML dan mengharapkan orang lain mengandalkan adalah pilihan yang buruk. Kebanyakan kode C # yang saya temui tidak mendokumentasikan metode secara lengkap dan konsisten dengan Komentar Dokumentasi XML. Dan kemudian ada masalah yang lebih besar yang tanpa pengecualian yang dicentang di C #, bagaimana Anda bisa mendokumentasikan semua pengecualian yang dilemparkan metode Anda untuk tujuan pengguna API Anda mengetahui cara menangani semuanya secara individual? Ingat, Anda hanya tahu tentang yang Anda lempar sendiri dengan kata kunci lempar dalam penerapan Anda. API yang Anda gunakan di dalam implementasi metode Anda mungkin juga memunculkan pengecualian yang tidak Anda ketahui karena mereka mungkin tidak didokumentasikan dan Anda tidak menanganinya dalam implementasi Anda, jadi mereka akan meledak di hadapan pemanggil Anda. metode. Dengan kata lain,

  2. Andreas menghubungkan wawancara dengan Anders Hejlsberg dalam jawaban di sini tentang mengapa tim desain C # memutuskan untuk tidak mengecek pengecualian. Tanggapan akhir untuk pertanyaan asli tersembunyi dalam wawancara itu:

Pemrogram melindungi kode mereka dengan menulis try akhirnya ada di mana-mana, sehingga mereka akan mundur dengan benar jika terjadi pengecualian, tetapi mereka sebenarnya tidak tertarik untuk menangani pengecualian.

Dengan kata lain, tidak ada yang tertarik dengan jenis pengecualian apa yang dapat diharapkan untuk API tertentu karena Anda akan selalu menangkap semuanya di mana-mana. Dan jika Anda ingin benar-benar peduli tentang pengecualian tertentu, cara menanganinya terserah Anda dan bukan seseorang yang menentukan tanda tangan metode dengan sesuatu seperti kata kunci lemparan Java, yang memaksa penanganan pengecualian tertentu pada pengguna API.

-

Secara pribadi, saya terkoyak di sini. Saya setuju dengan Anders bahwa mengecek pengecualian tidak menyelesaikan masalah tanpa menambahkan masalah baru yang berbeda. Sama seperti dengan komentar dokumentasi XML, saya jarang melihat kode C # dengan semuanya dibungkus dengan blok akhirnya mencoba. Rasanya bagi saya meskipun ini memang satu-satunya pilihan Anda dan sesuatu yang tampak seperti praktik yang baik.

Tobias
sumber
3

Sebenarnya tidak memeriksa pengecualian di C # dapat dianggap sebagai hal yang baik atau buruk.

Saya sendiri menganggapnya sebagai solusi yang baik karena pengecualian yang dicentang memberi Anda masalah berikut:

  1. Pengecualian Teknis bocor ke lapisan bisnis / domain karena Anda tidak dapat menanganinya dengan benar pada level rendah.
  2. Mereka termasuk dalam tanda tangan metode yang tidak selalu cocok dengan desain API.

Karena itu di sebagian besar aplikasi yang lebih besar Anda akan sering melihat pola berikut saat dicentang Pengecualian terjadi:

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

Yang pada dasarnya berarti meniru cara C # / .NET menangani semua Pengecualian.

Johannes Wachter
sumber
Saya tidak bisa membayangkan bagaimana pengecualian yang dicentang akan bercampur dengan lambda!
Gabe
@ Gabe: Saya yakin Anda dapat menemukan beberapa konsep yang memungkinkan Anda untuk mencampurnya, tetapi seperti yang saya katakan, pengecualian yang dicentang ada di Java juga sebagian besar bukan praktik yang baik, terutama di aplikasi yang lebih kompleks. Jadi ada baiknya mereka tidak ada di C #.
Johannes Wachter
3

Anda bertanya tentang ini:

Melempar ulang Pengecualian

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

atau

static void Main() 
    {
        string s = null;

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

        Console.Write("The string s is null"); // not executed
    }
Pranay Rana
sumber
3
1 untuk digunakan throw. Dengan menggunakannya, pelacakan tumpukan tidak akan hilang.
Giuseppe Accaputo
2

Ada beberapa kemiripan sekilas antara .Net CodeContract EnsuresOnThrow<>dan throwsdeskriptor java , keduanya dapat memberi sinyal ke pemanggil sebagai jenis pengecualian yang dapat dimunculkan dari suatu fungsi atau metode, meskipun ada juga perbedaan utama antara 2:

  • EnsuresOnThrow<>lebih dari sekadar menyatakan pengecualian mana yang dapat dilemparkan, tetapi juga menetapkan kondisi di mana pengecualian tersebut dijamin akan dilemparkan - ini bisa menjadi kode yang sangat memberatkan dalam metode yang dipanggil jika kondisi pengecualian tidak mudah untuk diidentifikasi. Java throwsmemberikan indikasi pengecualian mana yang dapat dilemparkan (mis. IMO fokus di .Net berada di dalam metode yang berkontraksi untuk membuktikannya throw, sedangkan di Java fokus bergeser ke pemanggil untuk mengakui kemungkinan pengecualian).
  • .Net CC tidak membuat perbedaan antara pengecualian Dicentang vs Tidak Dicentang yang dimiliki Java, meskipun manual CC bagian 2.2.2 menyebutkan

"gunakan kondisi akhir yang luar biasa hanya untuk pengecualian yang diharapkan pemanggil sebagai bagian dari API"

  • Dalam .Net pemanggil dapat menentukan apakah akan melakukan sesuatu dengan pengecualian atau tidak (misalnya dengan menonaktifkan kontrak). Di Java, pemanggil harus melakukan sesuatu , meskipun pemanggil menambahkan throwspengecualian yang sama pada antarmukanya.

Kode Kontrak manual di sini

StuartLC
sumber
0

Jika tujuan metode c # adalah untuk hanya melempar pengecualian (seperti yang dikatakan tipe pengembalian js) saya akan merekomendasikan hanya mengembalikan pengecualian itu. Lihat contoh di bawah ini:

    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;
    }

MENGAKUI
sumber
-1

Bagi mereka yang bertanya-tanya, Anda bahkan tidak perlu menentukan apa yang Anda tangkap untuk meneruskannya ke metode selanjutnya. Jika Anda ingin semua penanganan kesalahan Anda dalam satu utas utama, Anda dapat menangkap semuanya dan meneruskannya seperti ini:

try {
    //your code here
}
catch {
    //this will throw any exceptions caught by this try/catch
    throw;
}
Simon Jensen
sumber
Harap edit beberapa jawaban. Saya tidak sengaja mengklik -1. Saya tidak dapat menghapusnya sampai Anda membuat perubahan apa pun.
proximab