C#でJavaスタイルのスローキーワードを使用する方法


89

Javaでは、このthrowsキーワードにより、メソッドはそれ自体では例外を処理せず、呼び出し元のメソッドに例外をスローすることを宣言できます。

C#に同様のキーワード/属性はありますか?

同等のものがない場合、どのようにして同じ(または類似の)効果を達成できますか?

回答:


75

Javaでは、例外を処理するか、throwsキーワードを使用してメソッドをスローする可能性があるメソッドとしてメソッドをマークする必要があります。

C#にはこのキーワードまたは同等のキーワードがありません。C#のように、例外を処理しないと、キャッチされるまで、またはキャッチされない場合はプログラムが終了するまで、バブルアップします。

それを処理したい場合は、次のように再スローできます:

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

1
「泡立つ」、これはこれがJavaのthrows句を持つすべてのメソッドと同等であることを意味しますか?
Louis Rhys 08

1
@Louis RH-一種。これは、例外が処理されない場合、処理されるまで各呼び出し関数を介して呼び出しチェーンを上っていくことを意味します。
2010

1
@Louis RHは完全ではありません。つまり、コードをコンパイルするには、少なくともMainで例外をキャッチする必要がありました。C#はチェック済みの例外を認識していないため、それらをキャッチするかどうかはユーザー次第です。
Johannes Wachter 2010

1
@jwatcher:メインメソッドにもスロー句を含めることができます。
ルイス・リース

4
@AshishKamble-ええ。意見の問題。例外処理は.NETでは異なります。何が「良い」かを知っていると思い込まないでください。
2018年

105

opは、キーワードではなく、Javaのthrows節に相当するC#について質問していthrowます。これはJavaのメソッドシグネチャで使用され、チェックされた例外がスローされる可能性があることを示します。

C#では、Javaのチェック例外に直接相当するものはありません。C#には同等のメソッドシグネチャ句はありません。

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

に翻訳する

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

30

はい、これは古いスレッドですが、答えをググるときに古いスレッドを頻繁に見つけるので、見つけた便利なものを追加すると思いました。

Visual Studio 2012を使用している場合は、IDEレベルの「スロー」相当を可能にするために使用できる組み込みツールがあります。

上記のようにXML Documentation Commentsを使用する場合、<exception>タグを使用して、メソッドまたはクラスによってスローされる例外のタイプと、それがスローされるタイミングまたは理由に関する情報を指定できます。

例:

    /// <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、これがあなたの答えです。私は推測throwsしていますが、JAVAはおそらく、開発者に情報を提供することを除いて、ランタイムにとって何の意味もありません。同様に、@ mvanellaがここで指摘したのは、C#でまったく同じことを行う方法です。この "xmlドキュメント"の方がより重要な目的があることを知っていると思います。このスレッドは古いことを知っています。
Hari Lubovac 2016年

実際、Javaは、throws節で明示的に指定されていないか、throwコマンドによってスローされない限り、例外をバブルアップしません。つまり、RunTimeExceptionが発生し、発生したのと同じメソッドで処理されない場合、実行はそこで停止します。
ペドロリマ

18

これが私がbytes.comで見つけた同様の質問への回答です

短い答えはノーです。C#にはチェック済みの例外はありません。言語の設計者は、このインタビューでこの決定について議論します。

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

あなたが得ることができる最も近いのは、XMLドキュメントでタグを使用し、NDocで生成されたドキュメントをコード/アセンブリと共に配布して、他の人があなたがスローした例外を確認できるようにすることです(これは、MSDNドキュメントで正確にMSが行っていることです)。未処理の例外についてコンパイラに通知することはできませんが、Javaで慣れている場合と同様です。


7

ここでほとんどの回答を終えた後、いくつかの考えを追加したいと思います。

  1. XMLドキュメントのコメントに依存し、他の人に依存することを期待するのは適切な選択ではありません。私が出会ったほとんどのC#コードは、XMLドキュメントコメントでメソッドを完全かつ一貫してドキュメント化していません。そして、C#でチェックされた例外がなければ、APIユーザーがそれらすべてを個別に処理する方法を知るためにメソッドがスローするすべての例外をどのように文書化できるかという大きな問題がありますか?覚えているのは、実装でthrowキーワードを使用して自分で投げたものについてのみ知っていることです。メソッドの実装内で使用しているAPIは、ドキュメントに記載されていない可能性があり、実装でそれらを処理していないため、知らない例外をスローする可能性があります。方法。言い換えると、

  2. Andreasは、C#設計チームがチェックされた例外に反対する理由をここで答えたAnders Hejlsbergへのインタビューをリンクしました。元の質問に対する最終的な応答は、そのインタビューに隠されています。

プログラマーは、try finallyをどこにでも書いてコードを保護するため、例外が発生した場合に正しくバックアウトしますが、実際には例外の処理には関心がありません。

つまり、すべての場所で常にすべてのAPIをキャッチするため、特定のAPIでどのような例外が発生する可能性があるのか​​を誰も気にする必要はありません。特定の例外を本当に気にかけたい場合、それらを処理する方法はあなた次第であり、Javaのthrowsキーワードなどでメソッドシグネチャを定義して、APIユーザーに特定の例外処理を強制するのではありません。

-

個人的に、私はここで引き裂かれています。例外をチェックしても問題が解決されないのは、新しい別の問題を追加しない限り、アンダース氏に同意する。XMLドキュメントのコメントと同じように、C#のコードで、すべてがtry finallyブロックにラップされているのはめったにありません。これは確かにあなたの唯一の選択肢であり、良い習慣のように思えるものですが、それは私には感じられます。


3

実際にC#で例外をチェックしなかったのは、良いことでも悪いことでもあります。

チェックされた例外は次の問題を提供するので、私自身はそれが良い解決策であると考えています:

  1. 低レベルでは適切に処理できないため、ビジネス/ドメインレイヤーにリークする技術的な例外。
  2. それらはメソッドのシグネチャに属していますが、APIの設計で常にうまくいくとは限りません。

そのため、ほとんどの大きなアプリケーションでは、チェックされた例外が発生すると、次のパターンが頻繁に表示されます。

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

これは基本的に、C#/。NETがすべての例外を処理する方法をエミュレートすることを意味します。


チェックされた例外がラムダとどのように混ざるかは想像できません!
Gabe

@Gabe:きっとそれらを組み合わせることができるいくつかのコンセプトを思いつくと思いますが、私が言ったように、チェック例外はJavaにもあり、特により複雑なアプリケーションではほとんどお勧めできません。したがって、C#にはないのは良いことです。
Johannes Wachter 2010

3

あなたはこれについて尋ねています:

例外の再スロー

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

または

static void Main() 
    {
        string s = null;

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

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

3
を使用するための+1 throw。それを使用することにより、スタックトレースが失われることはありません。
ジュゼッペアカプト2010

2

.Net CodeContract EnsuresOnThrow<>とjava throws記述子の間には、いくつかの一時的な類似点があります。どちらも、関数またはメソッドから発生する可能性のある例外のタイプとして呼び出し元に通知できますが、2には大きな違いもあります。

  • EnsuresOnThrow<>どの例外をスローできるかを示すだけでなく、例外がスローされることが保証されている条件も規定しています。例外条件を特定するのが簡単ではない場合、これは呼び出されたメソッドで非常に面倒なコードになる可能性があります。Java throwsは、どの例外がスローされる可能性があるかを示します(つまり、.MOでのフォーカスは、throw、ありますが、Javaの場合、フォーカスは呼び出し元に移り、例外の可能性を確認します)。
  • .Net CCは、Javaが持っているチェック例外とチェックされていない例外を区別していませんが、CCマニュアルのセクション2.2.2では、

「例外的な事後条件は、呼び出し元がAPIの一部として予期する必要がある例外にのみ使用してください」

  • .Netでは、呼び出し元は例外を除いて何かを行うかどうかを決定できます(たとえば、契約を無効にすることによって)。Javaでは、呼び出し側throws、インターフェイスに同じ例外のを追加した場合でも、何かを行う必要があります。

コード契約マニュアルはこちら


0

c#メソッドの目的が例外のみをスローすることである場合(jsの戻り値の型のように)、その例外を返すことをお勧めします。以下の例をご覧ください。

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

0

不思議に思う人のために、次のメソッドに渡すために何をキャッチするかを定義する必要さえありません。1つのメインスレッドですべてのエラー処理が必要な場合は、次のようにすべてをキャッチして渡すことができます。

try {
    //your code here
}
catch {
    //this will throw any exceptions caught by this try/catch
    throw;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.