• ベストアンサー

C# 例外が発生しないことの保障

Javaと比較して書きます。 Javaで記述した場合: public class JavaClass {  public static SampleClass s = new SampleClass(); } C#で記述した場合: public class CSharpClass {  public static SampleClass s = new SampleClass(); } JavaでもC#でも、同じコードを記述しているように見えますが、Javaではnew SampleClass()コンストラクタで例外が発生しない事が分かっているのに対して、C#の場合では例外が発生しないとは言い切れません。 これは、Javaでは、例外をスローする可能性のあるメソッド宣言では、その全てについてthrows宣言をしなければいけないのに対して、C#にはこの制約が存在しないことが原因です。 これについて何が困るかといいますと、C#で、static宣言な変数や静的コンストラクタで安易にメソッド呼び出し等を行うと、キャッチできなくなってしまいます。 public class Exceptionner {  public Exceptionner()  {   throw new ApplicationException("Exceptionnerクラスの例外");  } } public class SampleClass {  public static Exceptionner e = new Exceptionner(); // ここで例外が発生するが、キャッチできない。 } public class MyEntryPoint {  public static void Main()  {   try   {    SampleClass s = new SampleClass();   }   catch (Exception e)   {    // System.ApplicationExceptionでなくSystem.TypeInitializationExceptionとなる。    // つまり、元の例外の情報は失われている    Console.WriteLine(e.GetType());   }  } } これを現在漠然と問題視していますが、何かよい解決策はありませんでしょうか。 望んでいる解決策: ・C#でもメソッドが例外を返さないという保障がソースレベルでメソッドやコンストラクタに宣言可能? ・C#では例外をちゃんとキャッチしなくてもスマートに記述することが可能? ・問題視する必要がない?(whyも含めて)

質問者が選んだベストアンサー

  • ベストアンサー
  • bleis
  • ベストアンサー率68% (11/16)
回答No.3

そもそも、Java の検査例外って使いやすいですかね? 手前味噌ですが、例外についてのエントリです。 http://d.hatena.ne.jp/bleis-tift/20090809/1249825777 で、望まれている解決策ですが、 1 番目は「ない」です。 2 番目は、catch されなかった例外を処理するための仕組みがあるため、それを使用します。 例えば、AppDomain.UnhandledException や、Application.ThreadException、Application_Error ハンドラなどを使用します。 3 番目は、「問題視する必要がないなんて言えない」でしょう。 例外が起きたときの対処方法は、「何もしない」ことを選択したとしても、考える必要はあります。 「何を考える必要があるか」は上で紹介したエントリを参考にしてください。 例外・・・難しいですよね。

nsnaago
質問者

お礼

ありがとうございます。 確かに、Javaでは少々、例外に頼りすぎていた所もあったかもしれません。 が、Javaの標準ライブラリ自体がそういう書き方をしていることも事実なので、その言語の慣習の問題でもあるんでしょうね。 JavaからC#に言語を変えたら、また慣習も習得しなおす必要がありそうです。 AppDomain.UnhandledExceptionやApplication.ThreadException等の存在は知りませんでした。 これらについてはじっくり検証する必要がありそうです。

その他の回答 (2)

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.2

問題視する必要はない。ようです(^-^;)。 1. Javaでも実行時例外(RuntimeException)は発生する可能性がある。 Exceptionはthrows句の記述がないと発生できませんが、RuntimeExceptionは 関係なく発生する可能性があります。 2. C#の例外処理は本来Javaの実行時例外に相当するものを扱う。 逆にC#ではJavaのような発生可能性を宣言するタイプの例外は扱わず そういうものは例外ではなく返値として返すのが基本です。 # C#は使ったことがないので詳細は知りません

nsnaago
質問者

お礼

そうですよね。 1について RuntimeExceptionはcatchしなくてもコンパイル時点では気づかないこともありますよね。 2について bleisさんの参照リンク先の、「例外を使わなくても正常動作するプログラムを作成する」ために必要なことですね。 だんだんとC#のほうが正しいのかと思えてきました。

回答No.1

ちょっと前に回答した物がありますので,まずはこちらを参照してみてください。 簡単に言うと,「Javaと.NET Frameworkでは例外に対しての考え方が違う」です。 QA: 5185119 http://okwave.jp/qa5185119.html > ・C#でもメソッドが例外を返さないという保障がソースレベルでメソッドやコンストラクタに宣言可能? できません (Javaでもできないけど……RuntimeExceptionとかErrorとか)。 > ・C#では例外をちゃんとキャッチしなくてもスマートに記述することが可能? > ・問題視する必要がない?(whyも含めて) そもそも,例外をcatchする状況って非常に限られますが……。 Site: むやみにキャッチしないでね。ゴールキーパー以外はハンドで反則ですよ。 - NAL-6295の舌先三寸 http://d.hatena.ne.jp/NAL-6295/20050909/p1 あと, > // System.ApplicationExceptionでなくSystem.TypeInitializationExceptionとなる。 > // つまり、元の例外の情報は失われている ですが,これは認識が誤っており,情報は残っています。 MSDN: TypeInitializationException クラス (System) http://msdn.microsoft.com/ja-jp/library/system.typeinitializationexception.aspx >TypeInitializationException の InnerException プロパティは、その発生原因である例外を保持します。 RemotingException等でも起こりえるので,Exception.InnerExceptionもちゃんと調べた方がよいです。 MSDN: Exception.InnerException プロパティ (System) http://msdn.microsoft.com/ja-jp/library/system.exception.innerexception.aspx

nsnaago
質問者

お礼

前半の内容については、先の2人の内容とおおまかにいうと同じですね。(そう解釈しました) やはりそれが正しいと認識したほうがよさそうです。 で、後半の内容については、(System.TypeInitializationExceptionをよく調べなかったのがいけなかったのですが)うれしい内容でした。 C#のコーディングのしかたのイメージがつかめてきました。 みなさんありがとうございました。

関連するQ&A

  • 他ファイルで定義された自作例外の受け方

    他ファイルで定義された自作例外の投げ方と受け方を 教えて下さい。 // ------ Class.java ---> import java.io.*; public class Class1 {  static Class2 oClass2;  public static void main (String[] args)  {   try {    oClass2 = new Class2();    System.out.println("main");    oClass2.vfFunc();   } catch (MyException e) {    System.out.println("catch MyException");   } catch (Exception e) {    System.out.println("catch Exception");   }  } } // <------ Class1.java --- // ------ Class2.java ---> import java.io.*; public class Class2 {  public Class2()  {   System.out.println("Class2コンストラクタ");  }  public void vfFunc()  {   System.out.println("Class2 vfFunc");   throw new MyException();  }  public class MyException extends Exception  {   public MyException()   {    System.out.println("MyException");   }  } } //<------ Class2.java ---

    • ベストアンサー
    • Java
  • 例外、null

    Cinクラスでは,BufferedReaderクラスで定義されたreadLineメソッドを使って, 一行ずつ入力を行っている。 class Cin { private static BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); public static String getLine() { String s = ""; try { s = in.readLine(); } catch (IOException e) { System.out.println("IO error!"); System.exit(1); } return s; } } このreadLineメソッドは,入力の終わりに到達するとnullを返し, それ以外の入力エラーがあるとIOException(Exceptionクラスのサブクラス)を投げる。 また入力の終わりに到達したことを,例外を用いて通知することも可能である。 readLineメソッドが,入力に関する状態を示すのに,「例外」、「nullを返す」 という二つの方法を使っているのにはどういう理由があるのか教えて下さい。

  • C++の例外処理について

    C++にjavaのような例外処理ができるのを知りました 構文は try { stat1 } catch(except-decl) { stat2 } finally { stat3 } stat4 ただし stat1:例外が発生する可能性があるステートメント stat2:例外が発生したときに実行するステートメント stat3:例外が発生しなくても実行するステートメント stat4:ステートメント except-decl:捕獲する例外の宣言 です ここで質問です (1) 冷害が発生したときstat4は実行されるのでしょうか? されない場合にはその後どう言う処理がなされるのでしょうか? (2) except-declはどうのような記述がなされるのでしょうか? (4) 例外を発生させる構文 throw except (except:発生させる冷害) のexceptの部分にはどのような記述がなされるのでしょうか? よろしくお願いします

  • 例外処理についてお願いします!!

    下のプログラミングについていくつか質問があります。 (1) プログラムの冒頭に来るpublic static void main(String[] args)を今まで気にしていなかったのですが これはどういうことですか?これもメソッドのひとつなんですか?このプログラムではpublic static void main(String[] args)でメソッドを定義してそれをetest( )メソッドで開いているという感じでしょうか? それとetstってどこから来たのかわかります?作者が勝手につけた名前だそうですが。 (2)FileReader fr = new FileReader("xfile.txt"); のところがわかりません。これはどういう意味ですか? public static void main(String[] args) { public static void etst( ) { try { // try節を書く FileReader fr = new FileReader("xfile.txt"); } catch (FileNotFoundException e) { // FileReader( )対応catch節 System.out.println("例外1: " + e); // 例外情報を表示 return; // 戻る } catch (IOException e) { // Close( )対応catch節 System.out.println("例外2: " + e); // 例外情報を表示 return; // 戻る } System.out.println("ファイルは正しくオープンされました"); } } } よろしくお願いします!!

    • ベストアンサー
    • Java
  • 呼び出し側ってなんですか?

    下に抜粋した本の解説の部分がわかりません。「呼び出し側」ってなんですか? -------------------------------------------------- このプログラムのetst( )メソッドでは、スロー宣言「throws FileNotFoundException」が行われます。 記述(1)でエラーが発生したら、その情報を呼び出し側に送り、そこでetst( )の処理は終わりになるため、記述(2)は実行されません。記述(1)でエラーが発生しなかった場合は、記述(2)が実行されます。 import java.io.*; public class JcReig3 { // JcReig3.java [java] public static void main(String args[]) { try { etst(); } catch (FileNotFoundException e) { // 呼び出し側でcatch節を書く System.out.println("例外発生: " + e); } } // こちらはthrows宣言を書く public static void etst() throws FileNotFoundException { FileReader fr = new FileReader("xfile.txt"); // (1) System.out.println("正しくオープンされました"); // (2) } }

    • ベストアンサー
    • Java
  • mainメソッドのthrows節で設定した例外はどこでcatchされる

    mainメソッドのthrows節で設定した例外はどこでcatchされる? java初心者です。 例えば、mainメソッドの中でAというメソッドが呼ばれるとします。 そのAについての宣言文(定義文)にthrows節が書かれているような場合、 mainメソッド内で、Aを呼び出す際、Aの実行の中で、もし例外が発生した場合には、 mainでその例外をキャッチして処理するよう、mainの記述を行う必要があるかと思います。 では、mainメソッド自体に設定したthrows節(つまり、 public static void main(String[] args) throws TestException{ ~略~ } という宣言) については、 その例外(ここでは、TestException)は、どこでcatchすることになるのでしょうか? もしや、「投げっぱなし」ということなのでしょうか? mainメソッド自体は、基本的に他のメソッドから呼ばれるものではないかと思うので、 mainメソッドでスローした例外の受け取り場所がわからなくて質問させていただきました。 色々調べたつもりなのですが、よくわからなくて困ってしまいました。 あまりに初歩すぎて、どこにも書かれていないのかなんなのか、 その説明が見当たらないこと自体にも、疑問を感じている次第です。苦笑 以上、どなたか、宜しくお願い致します。

    • ベストアンサー
    • Java
  • 例外処理がまったくわかりません!!

    下のプログラミングについていくつか質問があります。 (1)etest()メソッドってなんですか? (2)存在しないファイルを開くってどういうことですか? (3)FileReader( )対応catch節、Close( )対応catch節ってなんですか? (4)あと、プログラミングあとの本の解説の部分がよくわかりません。抜粋してみます。 「一般的な例外クラスはxxxExceptionというクラス名をしています。このタイプの例外クラスはみな「Exception例外クラス」をスーパークラスにしています。この場合、「catch(Exception e)」を使うとすべてのxxxException例外を補足できるという仕様になっています。ですから下のetest( )メソッドは次のように、ひとつのcatch節で記述することができます。このようにしても表示される4エラーメッセージ(eで指示)は、正しく発生例外(FileNotFoundExceptionまたはIOException) 対応のものになります。」 public static void etest( ) { try { // try節を書く FileReader fr = new FileReader("xfile.txt"); } catch (FileNotFoundException e) { // FileReader( )対応catch節 System.out.println("例外1: " + e); // 例外情報を表示 return; // 戻る } catch (IOException e) { // Close( )対応catch節 System.out.println("例外2: " + e); // 例外情報を表示 return; // 戻る } System.out.println("ファイルは正しくオープンされました"); } } よろしくお願いします。

    • ベストアンサー
    • Java
  • C# マルチスレッドにおける例外処理

    下記のようなデリゲートを利用したマルチスレッドのプログラムを組みました。 しかし、マルチスレッド内で例外がおきても、正常にプログラムが終了してしまいます。 (try-catchでも例外を捕捉できません) マルチスレッドプログラムにおいて、例外を捕捉するにはどうすれば、いいのでしょうか? using System; using System.Threading; class Class1 { delegate void delg(); public static void Main() { delg d = new delg(multi); d.BeginInvoke(new AsyncCallback(call), null); //マルチスレッド開始 System.Threading.Thread.Sleep(500); //マルチスレッドで例外を強制的に投げているので、 //ここまでたどり着く前にアプリケーションが落ちるはず。 //しかし、実際には正常終了。 Console.WriteLine("メインメソッド 正常終了"); } public static void multi() { Console.WriteLine("マルチスレッドで実行中"); throw new Exception(); //例外を強制的に投げる。 } public static void call(IAsyncResult ar) { Console.WriteLine("コールバックメソッド実行"); } }

  • 例外処理について

    こんにちは。 とあるメソッドで例えば 「void openErrorFile(){」とあるのですが、 メソッド内部で } catch (Exception e) { throw new RuntimeException();} と例外をThrowしています。 この場合、メソッドの定義「openErrorFile()」にはThrows句を 付ける必要は無いのでしょうか?。 すみませんがご教授願います。

    • ベストアンサー
    • Java
  • コンストラクタでの例外は不可能なのか。

    曖昧な記憶なのですが、コントラクタで例外を発生させてはいけないというような記述を見たことがあります。 質問なのですが、 1.そもそも本当にコントラクタは例外を発生させてはいけないのか? 2.なぜコントラクタの例外は問題となるのか? 3.newなどの関数は例外を発生させるが、コントラクタ内でキャッチすれば問題ないのか? 以上、お願いします。