13

Visual BasicではOn Error Resume Next、プログラムの先頭に記述し、プロジェクト全体でエラーが抑制されました。

ここC#では、この機能がとても恋しいです。try-catchすべての手順の通常の処理は、非常に時間がかかるだけでなく、望ましくない影響をもたらします。エラーが発生した場合、処理されたとしても、コードは発生した時点から続行されません。を使用On Error Resume Nextすると、コードはエラーのポイントから続行され、エラーの原因となった関数呼び出しだけがスキップされます。

私はまだC#に深く関わっていませんが、C#にはプリミティブよりも優れたエラー処理が存在する可能性がありますtry-catch

また、エラーが発生したモジュールまたは関数の名前と、エラーメッセージの行番号を教えてください。私のException知る限り、クラスはその機能を提供していません。アイデアはありますか(もちろん、自分のアプリケーションにプロセスクラスを含めずに管理されています)?

大規模なプロジェクトのエラーをどのように処理しますか?try-catchそれぞれのメソッドにを追加する必要がないことを願っています。どういうわけか、C#は多くのエラーをスローします-それは言語の典型的なようです。

私の問題のいくつかを解決するために私が見つけた私の解決策:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }

    [STAThread]
    static void Main()
    {
      Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); //setup global error handler
      Application.Run(new Form1());
    }

    private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
    {   
            MessageBox.Show("Unhandled exception: " + e.Exception.ToString()); //get all error information with line and procedure call
            Environment.Exit(e.Exception.GetHashCode()); //return the error number to the system and exit the application
    }

    private void button1_Click(object sender, EventArgs e)
    {
        string s = ""; s.Substring(1, 5); //Produce an error
    }

   }
4

6 に答える 6

32

何も起こらなかったかのようにエラーの後に続けることは、プログラミングのひどい方法です。

アカウントの新しい残高を計算できませんか?それは大丈夫です、それを0として保存しましょう。誰も知らないでしょう?

try/catchブロックは、実際に回復できるエラーが比較的少ないため、実際には比較的まれなはずです。通常、論理操作の先頭に1つのtry / catchブロックが必要です。これにより、失敗した場合にユーザーに通知して、他のまったく別の操作を続行できるようになります。または、使用しているアプリケーションの種類に応じて、アプリを完全に終了できます。書き込み。(ここでは、Webアプリが良い例です。厄介な永続的な副作用がないように注意して、リクエストを失敗させ、他のリクエストを引き続き処理することができます。)

回復できるエラーを合法的に期待できる場所がある場合は、それらの特定の例外をキャッチして適切に処理します(たとえば、データベースへの書き込みが失敗した場合は、ファイルへの書き込みにフォールバックします)。繰り返しになりますが、これらは比較的少なく、その間にあります。すべてのメソッド(またはすべてのクラス)でtry/ブロックを記述していることに気付いた場合は、例外を不適切に処理している可能性があります。catch

また、エラーが発生したモジュールまたは関数の名前と、エラーメッセージの行番号を指定したいと思います。Exceptionクラスは、私が経験した限り、その機能を提供していません。

はい、そうです。スタックトレースには、スタック内の各フレームのタイプ、メソッド、および行番号(使用可能な場合)と、もちろん(うまくいけば便利な)メッセージが表示されます。ああ、ある障害が別の障害によって引き起こされた場合は、ネストされた例外も発生する可能性があります。

どういうわけか、C#は常に実行時に多くのエラーをスローしますが、これは一般的な言語です。

いいえ、それはあなたが間違っていることを示唆しているだけです。

于 2012-07-21T21:42:49.330 に答える
18

いいえ。

元VBプログラマーとして言えば、これはこれまでに追加された中で最悪で最も悪用された機能です。代わりにアイデアは次のとおりです。

  1. エラーにならないコードを書く...実際に問題となる何かが起こらない限り。これには、何かをする前に仮定を確認することが含まれる場合があります。素晴らしい:それを行う
  2. 予想していた問題のみをキャッチします。すべてのエラーを飲み込むことは、大規模な問題を求めているだけです

Jonがすでに述べたように、実際には、あらゆる場所で例外処理が必要になることはほとんどありません。通常、何か悪いことが起こったので、例外を上位の呼び出し元にバブルさせます。そして、私持っているときtry、それはより一般的にtry/ finallytry/ではなくcatch)-usingそしてlock(etc)は便宜上それらの特別な場合です。

于 2012-07-21T21:43:16.653 に答える
4

いいえ、できません。これはC#では不可能です(他の言語では不可能です)。

VBでのこれの本当の使用法は、コードの一部で、のようにエラー処理を行うことでしたtry / catch。有効にし、確認しErr.Number <> 0、作業を行い、エラーフローを復元するOn Error GoTo 0か、別のパスをたどるラベルにリダイレクトして、エラーを処理するか、実行を続行しOn Error GoTo someErrorCase:ます。

あなたは一人で、またはそれを正しく行わない人と一緒にプログラムすることを学んだに違いありません。エラーを無視することは悪い習慣であり、それ以上に、コードに従うのは恐ろしいことです。結局のところ、エラーが発生する可能性があります。

私を信じて。私はVBプログラマーでしたが、ベストプラクティスを読むのをやめたとき、それは啓発的でした。

さらにいくつか追加するために、使用してみてください。Option Explicitすべての変数を宣言する作業が増えるように聞こえるかもしれませんが、型チェックによっていくつかの一般的なエラーが制限されるため、コードの信頼性が高まります。

また、C#の例外は非常に便利で、必要なすべての情報が含まれています。例外自体に問題がない場合は、例外を開いて内部例外を調べてください(すべてのコードが上位レベルにあるため、Web用に開発するときは常に内部例外を調べています)。

于 2012-07-21T21:55:10.603 に答える
4

実際、例外はむしろ例外であり、常に発生するわけではありません。それらが発生した場合、それらが発生したことを知り、それらを処理するか、プロセスをシャットダウンする必要があります。ほとんどの場合、例外を処理せずに放置すると、非常に予期しない結果が発生します。

于 2012-07-21T21:42:18.180 に答える
2

あなたはそのVB機能を間違って使用してきましたが、幸運なことにC#のように使用することはできません。

VBでこの機能を使用する場合、エラーが発生する可能性のあるすべての操作の後にエラーステータスを確認する必要があります。正しく使用するtry...catchと、エラーが発生する可能性のあるすべての操作の周りにブロックを配置するよりもコードが少なくなりません。

したがって、C#でより多くのエラー処理を行う必要があると思われる場合は、以前はほとんどエラー処理を行っていませんでした。

于 2012-07-21T22:06:08.970 に答える
0

「OnErrorResumeNext」では、VBのエキスパートレベルのエラー処理である「インラインエラー処理」が可能です。概念は、エラーに基づいてアクションを実行するか、有益な場合はエラーを無視するかのいずれかで、エラーを1行ずつ処理することですが、コードを記述された順序で実行し、コードジャンプを使用しません。

残念ながら、多くの初心者は「On Error Resume Next」を使用して、すべてのエラーを無視することにより、アプリケーションを使用している人から能力の欠如または怠惰を隠しました。Try / catchはブロックレベルのエラー処理であり、.NET以前の世界では設計と実装によって中間的でした。

VB.NETの「OnErrorResumeNext」の問題は、実行中のコードのすべての行にerrオブジェクトが読み込まれるため、try/catchよりも遅いことです。

https://msdn.microsoft.com/en-us/library/aa242093(v=vs.60).aspx

実際のVBの経験がない中級のC#プログラマーは、別の「Microsoft Net」言語に対する奇妙な軽蔑のために、C#を唖然とさせ、機能を制限しようとすべきではないと言われています。次のコードを検討してください。

//-Pull xml from file and dynamically create a dataset.
 string strXML = File.ReadAllText(@"SomeFilePath.xml");
 StringReader sr = new StringReader(strXML);
 DataSet dsXML = new DataSet();
 dsXML.ReadXml(sr);

string str1 = dsXML.Tables["Table1"].Rows[0]["Field1"].ToString();
string str2 = dsXML.Tables["Table2"].Rows[0]["Field2"].ToStrin();
string str3 = dsXML.Tables["Table3"].Rows[0]["Field3"].ToStrin();
string str4 = dsXML.Tables["Table4"].Rows[0]["Field4"].ToString();
string str5 = dsXML.Tables["Table5"].Rows[0]["Field5"].ToString();

xmlが通常Field3の値を持っているが、そうでない場合もある場合。テーブルにフィールドが含まれていないという厄介なエラーが発生します。それが必要なデータではないので、そうでなければ私はあまり気にすることができませんでした。この場合、ON Error Resume Nextを使用すると、エラーを無視でき、Containsメソッドを使用してテーブル、行、列の組み合わせの存在を確認する変数を設定するコードの各行をコーディングする必要がなくなります。これは小さな例です。大きなファイルから何千ものテーブル、列、行の組み合わせを取り込む可能性があります。また、ここでは、文字列変数にこの方法でデータを入力する必要があると想定します。これは未処理のコードであり、問​​題が発生します。

VB.NETおよびONエラーを考慮して次の実装を再開します。

 On Error Resume Next

        Dim strXML As String = File.ReadAllText("SomeNonExistentFileCausingAnErrorCondition.xml")
        If String.IsNullOrEmpty(strXML) Then
            strXML = strSomeOtherValidXmlThatIUseWhenTheFileIsEmpty
        End If
        Dim srXmL As StringReader = New StringReader(strXML)
        Dim dsXML As DataSet = New DataSet()
        dsXML.ReadXml(srXmL)
        If Err.Number <> 0 Then
            MsgBox(Err.Number & Space(1) & Err.Description)
            Exit Sub
        End If

        Dim str1 As String = dsXML.Tables("Table1").Rows(1)("Field1").ToString()
        Dim str2 As String = dsXML.Tables("Table2").Rows(2)("Field2").ToString()
        Dim str3 As String = dsXML.Tables("Table3").Rows(3)("Field3").ToString()
        Dim str4 As String = dsXML.Tables("Table4").Rows(4)("Field4").ToString()

上記のコードでは、1つの考えられるエラー状態を処理するだけで済みました。ファイルのロード中にエラーが発生した場合でも。On Error Resume Nextを使用すると、実際に意図したとおりに再開でき、文字列の状態を確認して代替文字列を使用できました(ファイルの存在も確認して、ファイルエラーを回避できた可能性があることはよく知っていますが、それは何も入っていない良いファイルでした、strXMLは空の文字列になります)。ロードされたデータセットがそれ以降の残りの処理(必要に応じてエラーを無視して実行できる処理)にとって最も重要であったため、コードの残りの部分に重大なエラーが処理され、メソッドが終了しました。ファイルエラーを無視したか、エラー状態を確認してログに記録したため、ファイルエラーを無視できました。

RAD開発にはOnErrorResumeNextが必要です。C#は私の言語の選択ですが、多くの理由からVBほどRAD言語ではありません。すべてのプログラマーが、いくつかの主要な言語(つまり、C)が実行され、未処理のエラーで実行を停止しないことを理解してほしいと思います。必要と思われる場所でそれらをチェックするのは開発者の仕事です。On Error Resume Nextは、Microsoftの世界でそのパラダイムに最も近いものです。

幸いなことに、.NETはこれらの状況を処理するための多くの高度な選択肢を提供します。私は含むに逃げました。したがって、C#では、言語の知識レベルを強化する必要があり、C#言語仕様に従って、このような問題を適切に回避します。煩わしいスローアウェイエラーを含む可能性のあるコードの繰り返し行の大きなブロックを処理するためのソリューションを検討してください。

try
            {
                if (!File.Exists(@"SomeFilePath.xml")) { throw new Exception("XML File Was Not Found!"); }
                string strXML = File.ReadAllText(@"SomeFilePath.xml");
                StringReader sr = new StringReader(strXML);
                DataSet dsXML = new DataSet();
                dsXML.ReadXml(sr);

                Func<string, string, int, string> GetFieldValue = (t, f, x) => (dsXML.Tables[t].Columns.Contains(f) && dsXML.Tables[t].Rows.Count >= x + 1) ? dsXML.Tables[t].Rows[x][f].ToString() : "";

                //-Load data from dynamically created dataset into strings.
                string str1 = GetFieldValue("Table1", "Field1", 0);
                string str2 = GetFieldValue("Table2", "Field2", 0);
                string str3 = GetFieldValue("Table3", "Field3", 0);
                //-And so on.

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            } 

try / catchブロックでは、ラムダ関数は、xmlによって動的に入力されたデータセットからプルされているすべてのテーブル、行、列の組み合わせの存在をチェックしています。これは行ごとにチェックできますが、多くの余分なコードが必要になります(ここでは、同じ量の実行コードがありますが、維持するために記述されたコードははるかに少なくなります)。残念ながら、これは「1行関数」のもう1つの悪い習慣と見なされる可能性があります。ラムダと無名関数の場合、私はそのルールを破ります。

.NETは、オブジェクトのステータスをチェックするための非常に多くの方法を提供しているため、On Error Resume Nextは、VBの専門家にとって、.NET以前ほど重要ではありませんが、それでも手元に置いておくと便利です。特に、速くて汚いコーディングをしないと時間の無駄になるようなものをコーディングしている場合はなおさらです。エキスパートレベルでVBを使用したことのある人は、On Error Resume Next(インラインエラー処理)が言語に追加された中で最悪の機能であると主張することはありません。しかし、それは初心者によって広く誤用されてきました。

于 2015-12-12T19:54:20.763 に答える