15

私は Windows 8 と C# の開発は初めてですが、Java プログラミングの経験はある程度あります。

したがって、Java で Json パーサー (たとえば) を作成しようとすると、try - catch ブロックを使用しないと実行できず、この方法で例外を処理できますが、C# で同じことをしようとすると(Windows 8) で、try - catch ブロックも使用しません。次のように機能します。

if (json != null)
{
        JObject jObject = JObject.Parse(json);

        JArray jArrayUsers = (JArray)jObject["users"];

        foreach (JObject obj in jArrayUsers)
        {
            ListViewMainViewModel user = new ListViewMainViewModel(
                (String)obj["email"],
                (String)obj["token"],
                (String)obj["institution"],
                (String)obj["uuidInstitution"]);

            usersList.Add(user);
        }
        return usersList;
    }

}

私が知っているように、正しい方法は JsonReaderException をキャッチすることですが、Visual Studio はそれについて警告しませんでした。eclipseを使用するJavaのように、一部のメソッドが例外をスローするかどうかを知る簡単な方法があるかどうかを知りたいです(try-catchブロックを実装するか、コードがコンパイルされないことが必須です)

4

4 に答える 4

29

そのためには、ドキュメントを参照する必要があります。C# にはthrowsキーワードがありません。

あなたが探しているものに対する用語は、チェックされた例外です。詳細については、C# FAQを参照してください。

于 2013-08-19T14:40:22.600 に答える
18

前述のように、C# にはチェック例外がありません。

チェック例外のアイデアは一見すばらしく聞こえますが、言語またはランタイムによってそれらを使用することを余儀なくされている人に話を聞くと、チェック例外には 3 つの大きな問題があると言うでしょう。

  • 彼らは消費するコーダーに彼らの意志を押し付けます。チェック例外は、その定義により、ランタイムからスローされる前に処理されることが期待されます。ランタイムは実質的に、コーダーに「これをスローしたときに何をすべきかを知っておく必要があるので、そうしてください」と伝えています。まず、考えてみてください。あなたは例外的に起こる何かを期待するように言われていますまさにその定義によるケース。第二に、あなたは何らかの形でそれを処理することが期待されています。例外が示す問題に実際に対処する能力があれば、それで問題ありません。残念なことに、私たちは常にその能力を持っているわけではありません。データ変換を実行する単純なフォーム アプレットを作成していて、何か問題が発生した場合にアプリケーションを猛烈な勢いで停止させたい場合、何もキャッチしないわけにはいきません。何かをスローする可能性のあるすべてのメソッドのすべての可能な呼び出しスタックを調べて、throws 句にスローできるものを追加する必要があります (または、非常に怠惰で、コードベースのすべてのメソッドに「throws Exception」句を配置します)。同様に、私のアプリができないように構築されている場合特定の例外をスローします。おそらく、潜在的なスロー可能オブジェクトとして指定していない、制御できないインターフェイスを実装しているためです。その場合、唯一のオプションは、それを完全に飲み込み、無効な可能性のある結果を呼び出し元に返すか、ラップすることです。 RuntimeException のようなチェックされていないスロー可能な型の例外をスローし、その方法でスローします (チェックされた例外メカニズム全体を無視しますが、これはもちろんお勧めできません)。

  • それらはSOLID、特に開閉原則に違反しています。チェックされた例外をコードに追加する変更を行い、その例外を処理できない場合は、メソッドのすべての使用法でそれを処理するか、例外をスローするものとしてマークする必要があります。再スローする使用法は、独自の呼び出し元が処理するか、同じ例外をスローするものとしてマークする必要があります。コードの特定の行で別のメソッドを呼び出すような大規模な変更を行うことで、考えられるすべてのコール スタックを追跡し、正常に動作していたコードに他の変更を加えて、コードがおそらくスローされる可能性があることを伝える必要があります。例外。

  • それらは、定義により漏れやすい抽象化を作成します。「throws」句を含むメソッドを使用する呼び出し元は、実際には、その依存関係に関するこれらの実装の詳細を知っている必要があります。次に、これらのエラーを処理したくない、または処理できない場合は、これらのエラーについて自身の消費者に通知する必要があります。メソッドがインターフェイス実装の一部である場合、問題はさらに複雑になります。オブジェクトがそれをスローするためには、すべての実装がその例外をスローするわけではなくても、インターフェイスはそれをスロー可能として指定する必要があります。

    Java は、例外クラスの複数レベルの階層を持つことでこれを軽減します。たとえば、すべての I/O 関連の例外は (想定される) IOExceptions であり、IO 関連の目的を持つメソッドを持つインターフェイスは、IOException をスローできるように指定することができ、特定の子 IOException をそれぞれ指定する責任から解放されます。ただし、これは解決するのとほぼ同じ数の問題を引き起こします。多数の IOExceptions があり、原因と解決策が大きく異なる可能性があります。そのため、実行時にキャッチした各 IOException に問い合わせて、その真の型を取得する必要があります (また、スローされる可能性のある特定のものを特定するための助けはほとんどまたはまったく得られません)。

編集:もう1つの大きな問題:

  • 彼らは、可能性のある例外状況を処理する唯一の方法が try-catch であると想定しています。C# に Java スタイルのチェック例外がある別の世界で C# を使用しているとします。呼び出し元から渡されたファイル名を指定して、メソッドでファイルを開いて読み取る必要があります。優れたコード作成者のように、 File.Existsを使用して、保護句にファイルが存在することを最初に検証します。(これは決して例外をスローしません。true を返すには、パスが有効で、パスで指定されたファイルが存在し、実行ユーザー アカウントが少なくともフォルダーとファイルへの読み取りアクセス権を持っている必要があります)。File.Exists が false を返す場合、メソッドは単にデータを返さず、呼び出し元は何をすべきかを知っています (たとえば、このメソッドがオプションの構成データを含むファイルを開き、それが存在しない場合、空白であるか破損している場合、プログラムはデフォルト設定を使用します)。

    ファイルが存在する場合は、File.Open を呼び出します。File.Openは 9 種類の例外をスローできますただし、File.Exists を使用して、プログラムを実行しているユーザーがファイルを読み取り専用で開くことができることを既に確認しているため、これらのいずれも発生する可能性はありません。ただし、チェック例外メカニズムは気にしません。使用しているメソッドは、これらの例外をスローできるように指定しているため、例外を処理するか、独自のメソッドが例外をスローできるように指定する必要があります。頼りになる答えは、それらを飲み込んでnullを返すことです(またはガード句を忘れて、File.Openの例外をキャッチして処理するだけです)が、それは最初にガード句で回避しようとしていたパターンです。

これは、悪の可能性さえ考慮していません。たとえば、開発者はチェックされていない例外をキャッチしてチェック済みの例外としてカプセル化する場合があります (たとえば、NullPointerException をキャッチして IOException をスローする)。何が悪いのかをよく表しています。

C# で代わりに使用するものに関する限り、ベスト プラクティスは、XML ドキュメント コメントを使用して、メソッドを使用している直接の呼び出し元に、メソッドから例外がスローされる可能性があることを通知することです。XML-doc は JavaDoc コメントに相当する .NET であり、ほとんど同じように使用されますが、構文が異なります (3 つのスラッシュの後に XML タグのシステムで囲まれたコメントが続きます)。例外のタグは簡単に指定できます。コードベースを効率的に文書化するには、 GhostDocをお勧めします。ただし、ドキュメント化されているメソッド内から明示的にスローされた例外の例外コメントのみを生成し、いくつかの空白を埋める必要があります。

于 2013-08-19T23:17:36.720 に答える
18

C# では、例外を処理する責任があります。これは、Java 実装よりも優れた方法です。実際には、例外は例外的あるべきです

この奇妙な (まだ一般的な) アンチパターンを考えてみてください。

try {


} catch (Exception ex) { /* Handler goes here */ }

それは正確にはどういう意味ですか?ここを通過するすべての例外を本当に処理するつもりですか? のようなものでもOutOfMemoryException?それはナッツです。この種のパターンがもたらす唯一のことは、実際にはアプリケーションを停止させるべき正当な例外を抑制することです。これは、Java のアプローチとかなり似ています。

Exceptionは、「環境が不可能な状態になった」というプログラマーへのフラグと考えてください。たとえば、ゼロで除算しようとしてシステムが をスローしたDivideByZeroException場合、これは失敗であるため、当然システムはこれを警告する必要があります。単純に問題を抑制します。それが実際にどのように役立つのでしょうか? 結局、これは非生産的であり、実際には不可能なアプリケーションの状態を隠しているだけです。アプリケーションでこれを頻繁に行うと、最終的には有毒な間違いのスラッジに発展します。うん!

例外は、多くの画面領域も占有します。ブロックをもう少し合理化してほしいと思うこともありtry/catch/finallyますが、そうすることで人々がより多くのブロックを使用するようになることを覚えているので、私はその立場をすぐに悔い改めました.

例外は、プログラマーが行っていることが意味をなさないことを伝える、プログラマー間の便利な通知です。明らかに、生の例外をユーザーに渡すべきではありません。同時に、地球上のすべての例外を処理しようとする必要はありません。この意味での「処理」は、通常、アプリケーションを失敗させるよりもはるかに悪い「抑制」に変換されるためです (優雅に) )。

于 2013-08-19T14:41:53.533 に答える