Frage

Wenn ich leere Fangblöcke für meinen C# Code einsehe, wird es dann ein Äquivalent für VB.NETs "Auf Fehlerbehebung Next" -Anweisung sein.

try
{
    C# code;
}

catch(exception)
{
}

Der Grund, warum ich dies frage, liegt daran try {} catch {} In meinem neuen Code gibt es eine bessere Alternative?

War es hilfreich?

Lösung

Ich habe festgestellt, dass VB -Programmierer oft mit vielen verschmutzt sind On Error Resume Next Aussagen aus (schlechter) Gewohnheit. Mein Vorschlag wäre zu Beginn mit nein unterdrückte Ausnahmen und sehen Sie, was tatsächlich bricht. Es gibt möglicherweise nicht so viele Probleme, wie Sie denken. Umgekehrt können Sie umgekehrt, je mehr Regressionstests Sie durchführen können, desto besser; Es kann einige Kantenfälle geben, die nur dann funktionieren, wenn Fehler ignoriert werden.

Letztendlich müssen Sie sich für eine Fehlerbehandlungsstrategie entscheiden, unabhängig davon, ob es sich um eine anmutige Abwicklung in vielen Versuchs-/Fangblöcken handelt oder Fehler auf einen Handler der obersten Ebene (beide Strategien haben ihre Verwendungen).

Wenn Sie am Ende einige Ausnahmen unterdrücken müssen, um eine Frist einzuhalten, zumindest Melden Sie diese Ausnahmen so, dass der nächste Entwickler, der an Ihrem Code arbeitet try/catch.

Andere Tipps

Obwohl dies manchmal akzeptabel ist, zeigt es im Allgemeinen einen Codegeruch an. Wenn Sie zu 100% sicher sind, dass Sie die Ausnahme, die aufgetreten ist sollte tun etwas.

Im Allgemeinen können Sie das gleiche Ergebnis mit gut gestalteter Code erzielen. Wenn Sie derzeit einen bestimmten Fehler haben, fügen Sie ihn Ihrer Frage hinzu. Wenn Sie jedoch nur aus Neugier fragen, gibt es kein Äquivalent, und das ist eine gute Sache.

Nein, es ist nicht dasselbe.

Wenn VB als nächstes für Fehler des Fehlers verwendet wird, würde VB zur nächsten Zeile überspringen, wenn ein Fehler auftritt. Mit Try/Catch springt die Ausführung zum Fangblock, wenn ein Fehler (Ausnahme) auftritt.

Sie müssen die analysieren On Error Resume Next Aussagen eins nach dem anderen und sehen Sie, was ihr Zweck ist. Einige mögen nur einen schlampigen Code sein, aber es gibt gültige Gründe dafür On Error Resume Next In Visual Basic 6.0 Code.

Einige Beispiele für die Verwendung On Error Resume Next In Visual Basic 6.0 Code:

  • So überprüfen Sie, ob ein bestimmter Schlüssel in einer visuellen Basic 6.0 -Sammlung vorhanden ist. Die einzige Möglichkeit, dies zu tun, besteht darin, auf das Element nach Schlüssel zuzugreifen und den Fehler zu bewältigen, der aufgeworfen wird, wenn der Schlüssel nicht vorhanden ist. Beim Konvertieren in .NET können Sie dies durch eine Überprüfung auf die Existenz des Schlüssels ersetzen.

  • Anschnur an eine Ganzzahl analysieren. In .NET können Sie verwenden TryParse.

Obwohl On Error Resume Next ist sicherlich mehr missbraucht als legitim verwendet, es gibt Orte, an denen es auch in VB.NET hilfreich wäre.

Betrachten Sie ein Programm, das einer großen Anzahl von Excel -Eigenschaften Werte zuweist, z. Spätere Versionen von Excel haben möglicherweise Eigenschaften, die frühere Versionen nicht unterstützen, und es ist nicht trivial herauszufinden, welche in jeder Version unterstützt werden. Das Programm sollte einen Wert zuweisen, wenn die Eigenschaft existiert, die Eigenschaft jedoch ignoriert, wenn eine ältere Version von Excel verwendet wird.

Der "richtige" Weg, dies mit VB.NET zu tun, besteht darin, zu bestimmen, welche Druckereigenschaften von jeder Version von Excel unterstützt werden, die verwendete Version lesen und nur Eigenschaften zuweisen, die in dieser Version implementiert sind. Das würde viel Forschung und etwas Code erfordern, alles für wenig Vorteil. On Error Resume Next wäre eine praktischere Lösung.

Und leider bin ich jetzt genau mit diesem Problem konfrontiert. Die Problemumgehung, die ich versuchen werde, besteht darin, eine Unterroutine zu schreiben, die nur einen Wert zuweist und Fehler ignoriert. Ich werde dieses Unterprogramm anstelle jeder Zuordnungsanweisung nennen. Nicht zu ärgerlich, aber auch nicht so groß.

"Auf Fehlerbehebung als nächstes" ermöglicht "Inline -Fehlerbehandlung", was die Experten -Level -Fehlerbehandlung in VB ist. Das Konzept besteht darin, die Fehlerzeile für Zeile zu verarbeiten, entweder eine Aktion basierend auf dem Fehler auszuführen oder den Fehler zu ignorieren, wenn es vorteilhaft ist - aber Code in der Sequenz ausführen, in der er geschrieben wird und nicht mit Codesprungs verwendet wird.

Leider verwendeten viele Anfänger, die als nächstes "beim Fehlerlebenslauf" verwendet wurden, um ihre mangelnde Fähigkeit zu verbergen, oder aus Faulheit von denjenigen, die ihre Anwendungen verwenden, indem alle Fehler ignoriert wurden. Try/catch IS Block Level-Fehlerbehandlung, das in der Welt vor der .NET durch Design und Implementierung mittel).

Das Problem mit "On Fehler -Lebenslauf als nächstes" in VB.NET besteht darin, dass das ERR -Objekt in jeder Zeile des Ausführungscodes geladen wird und daher langsamer ist als try/catch. Ich bin etwas alarmiert darüber, dass dieses Forum eine verrückte Antwort überprüft und beworben hat, die als nächstes eine schlechte Angewohnheit und einen Code -Müll verwendet hat. Dies ist ein C# Forum; Sollte es wirklich für C# -Programmierer verwendet werden, um Aufnahmen in eine andere Sprache zu machen, in der sie nicht gut vertraut sind?

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

Es heißt, dass intermediate C# -Programmierer ohne wirkliche VB -Erfahrung nicht versuchen sollten, C# wegen ihrer seltsamen Verachtung für eine andere "Microsoft Net" -Prache begrenzt zu halten, betrachten Sie den folgenden Code:

//-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();

Wenn der XML normalerweise einen Wert für Feld3 hat, aber manchmal nicht; Ich werde einen nervigen Fehler bekommen, dass die Tabelle das Feld nicht enthält. Ich könnte mich weniger interessieren, wenn dies nicht der Fall ist, weil es keine Daten benötigt. In diesem Fall würde ich beim nächsten Fehler als nächstes den Fehler nur ignorieren, und ich müsste nicht jede Codezeile um die Variablen einstellen, die nach Existenz der Tabelle, Zeile und Spaltenkombination mit Methoden überprüft werden. Dies ist ein kleines Beispiel; Ich könnte Tausende von Spalte, Zeilenkombinationen aus großen Dateien einziehen. Nehmen wir hier auch an, dass die String -Variablen auf diese Weise besiedelt werden müssen. Dies ist unberührtes Code und es wird Probleme geben.

Betrachten Sie eine VB.NET und bei der nächsten Implementierung von Fehlerbehebungen:

On Error Resume Next

        'Pull Xml from file And dynamically create a dataset.
        Dim strXML As String = File.ReadAllText("SomeFilePath.xml")
        Dim srXmL As StringReader = New StringReader(strXML)
        Dim dsXML As DataSet = New DataSet()
        dsXML.ReadXml(srXmL)

        'Any error above will kill processing. I can ignore the first two errors and only need to worry about dataset loading the XML.
        If Err.Number <> 0 Then
            MsgBox(Err.Number & Space(1) & Err.Description)
            Exit Sub 'Or Function
        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()

Im obigen Code musste nur eine mögliche Fehlerbedingung verarbeitet werden. Obwohl es zwei Fehler gab, bevor der dritte behandelt wurde. RAD -Entwicklungsbedürfnisse beim Nächsten Fehlerbehebung. C# ist meine Wahl der Sprachen, aber aus vielen Gründen ist es nicht so viel rAD -Sprache wie VB. Ich hoffe, alle Programmierer erkennen, dass mehrere große Sprachen (dh c) einfach laufen und die Ausführung nicht auf unberührten Fehlern stoppen. Es ist der Auftrag der Entwickler, nach ihnen zu suchen, wo sie für notwendig halten. Als nächstes ist es am nächsten zu diesem Paradigma in der Microsoft -Welt.

Glücklicherweise gibt .NET viele erweiterte Auswahlmöglichkeiten, um diese Situationen zu bewältigen. Ich entschied mich zu den Enthalten. In C# müssen Sie also Ihr Wissensniveau der Sprache verbessern, und Sie arbeiten nach der C# -Sprachspezifikation richtig um solche Probleme. Betrachten Sie eine Lösung für den Umgang mit einem großen Block mit sich wiederholenden Codezeilen, die einen nervigen Wurf -Fehler enthalten könnten:

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

Obwohl in einem Versuch/Catch -Block die Lambda -Funktion nach der Existenz jeder Tabelle, der Zeile, der Spaltenkombination, die aus dem Datensatz gezogen wird, der dynamisch von der XML besiedelt wurde, gezogen wird. Dies könnte eine Zeile nach der Zeile überprüft werden, würde jedoch viel überschüssiger Code erfordern (hier haben wir den gleichen Ausführungscode, aber weitaus weniger geschriebener Code für die Wartung). Dies könnte leider als eine weitere schlechte Praxis von "One -Line -Funktionen" angesehen werden. Ich breche diese Regel im Fall von Lambdas und anonymen Funktionen.

Da .NET bietet so viele Möglichkeiten, den Status von Objekten zu überprüfen. Als Nächstes für Fehler wird für VB -Experten nicht so wichtig wie vor .NET, aber dennoch schön zu haben. Besonders wenn Sie etwas codieren, das Zeitverschwendung wäre, nicht schnell und schmutzig zu codieren. Für Sie konvertiert Java zu C#; Schließen Sie sich der Microsoft -Welt an und geben Sie auf, so zu tun, Ihre Entwicklung von .NET selbst ist falsch und Sie sehen dumm aus. Ich möchte all die Funktionen, die ich in C# und VB und F# und jede andere Sprache erhalten kann, die ich verwenden muss. C# ist elegant, aber VB ist aufgrund seiner viel längeren Amtszeit weiterentwickelt, aber beide tun das "Gleiche" und verwenden dieselben Objekte. Lernen Sie sie beide gut oder wehren Sie sich bitte wider, entweder im Vergleich zu den Gesprächen zu kommentieren. Es ist für diejenigen von uns übel, die es seit Mitte der neunziger Jahre gibt, die Microsoft Technologies auf hohem Niveau verwenden.

Die Verwendung von "On Fehler -Lebenslauf Next" ist keine gute Idee für die Fehlerbehandlung (natürlich ist dies meine persönliche Meinung, aber die meisten Entwickler sind mir allerdings zustimmen). Wie andere Leute Ihnen in früheren Beiträgen beraten haben, verwenden Sie Try...Catch...Finally (ob in Vb.net oder c#).

Dies ist eine sehr intelligente Option für die Fehlerbehandlung, aber Sie ermöglichen es Ihnen auch, nichts mit dem Fehler (einem leeren Fangblock) zu tun :) Ich würde Ihnen vorschlagen, jede Codezeile (die Fehler verursachen kann) in separate Try...Catch Block, damit Sie die Möglichkeit haben, alles zu tun, was Sie wollen, wenn ein Fehler auftritt. Happy Coding Guys :)

Der ordnungsgemäße .NET -Ersatz für "On Fehler -Lebenslauf Weiter" ist die Verwendung von Try___ -Methoden. In Visual Basic 6.0, um herauszufinden, ob ein Schlüssel in einer Sammlung vorhanden war, musste man entweder die Sammlung manuell (schrecklich langsam) durchsuchen oder versuchen, sie zu indizieren und einen Fehler zu fangen, der aufgetreten ist, wenn sie nicht vorhanden war. In VB.NET unterstützt das Wörterbuchobjekt (das eine verbesserte Version der alten Sammlung ist) a TryGetValue Methode, die angibt, ob der Versuch, den Wert erfolgreich zu machen, ohne einen Fehler zu verursachen, wenn dies nicht der Fall war. Eine Reihe anderer .NET -Objekte unterstützen ähnliche Funktionen. Es gibt einige Methoden, die "versuchen", Äquivalente, aber nicht (zum Beispiel, nicht Control.BeginInvoke), aber es gibt ausreichend wenige von ihnen, die sie einzeln in a einwickeln Try/Catch ist nicht zu belastend.

Ich denke zufällig, dass die Leute, die "im Nächsten" Irrtum Resume "erfunden haben, etwas im Sinn haben, als sie es geschaffen haben. Die Antwort auf Ihre Frage wäre nein, dass dieses Konstrukt in C#nichts entspricht. Wir haben in C# und .NET viele Funktionen, die so hungrig nach Sorgfalt und Aufmerksamkeit sind, dass es nach einer Weile anstrengend ist, dem "außergewöhnlichen Verhalten" aller zu geraten. Wenn fast alles eine Ausnahme auswerfen kann, verliert das Wort selbst etwas. Sie befinden sich in einer Iteration und was sollten Sie tun, wenn nur wenige Tausende von Millionen Gegenständen außergewöhnlich sind? Nächstes könnte der Lebenslauf eine der praktischen Antworten sein.

Wie von @tim Medora gesagt, müssen Sie sich bemühen, einen solchen Ansatz beim Codieren zu vermeiden. In einigen Fällen ist es jedoch nützlich und es ist möglich, ein solches Verhalten zu emulieren. Hier ist eine Funktion und ein Beispiel für die Verwendung. (Beachten Sie, dass einige Codeelemente mit C#6 geschrieben wurden)

    /// <summary>
    /// Execute each of the specified action, and if the action is failed, go and executes the next action.
    /// </summary>
    /// <param name="actions">The actions.</param>
    public static void OnErrorResumeNext(params Action[] actions)
    {
        OnErrorResumeNext(actions: actions, returnExceptions: false);
    }

    /// <summary>
    /// Execute each of the specified action, and if the action is failed go and executes the next action.
    /// </summary>
    /// <param name="returnExceptions">if set to <c>true</c> return list of exceptions that were thrown by the actions that were executed.</param>
    /// <param name="putNullWhenNoExceptionIsThrown">if set to <c>true</c> and <paramref name="returnExceptions"/> is also <c>true</c>, put <c>null</c> value in the returned list of exceptions for each action that did not threw an exception.</param>
    /// <param name="actions">The actions.</param>
    /// <returns>List of exceptions that were thrown when executing the actions.</returns>
    /// <remarks>
    /// If you set <paramref name="returnExceptions"/> to <c>true</c>, it is possible to get exception thrown when trying to add exception to the list. 
    /// Note that this exception is not handled!
    /// </remarks>
    public static Exception[] OnErrorResumeNext(bool returnExceptions = false, bool putNullWhenNoExceptionIsThrown = false, params Action[] actions)
    {
        var exceptions = returnExceptions ? new Collections.GenericArrayList<Exception>() : null;
        foreach (var action in actions)
        {
            Exception exp = null;
            try { action.Invoke(); }
            catch (Exception ex) { if(returnExceptions) { exp = ex; } }

            if (exp != null || putNullWhenNoExceptionIsThrown) { exceptions.Add(exp); }
        }
        return exceptions?.ToArray();
    } 

Beispiel anstelle von:

        var a = 19;
        var b = 0;
        var d = 0;
        try { a = a / b; } catch { }
        try { d = a + 5 / b; } catch { }
        try { d = (a + 5) / (b + 1); } catch { }

du kannst:

            var a = 19;
            var b = 0;
            var d = 0;
            OnErrorResumeNext(
                () =>{a = a / b;},
                () =>{d = a + 5 / b;},
                () =>{d = (a + 5) / (b + 1);}
            );

Ich bin ein alter Hut bei VB6. Zuerst eine kurze Lektion ...

Als nächstes gibt es Gründe für den Fehler bei Fehlersumme. Meistens zur Lesbarkeit. In VB6 haben Sie zwei Möglichkeiten, um Fehler beim Einfangen zu implementieren. Sie können als nächstes eine "Inline" für Fehlerbehebung verwenden.

On Error Resume Next
<something that may throw an error>
If Err.Number <> 0 Then
   <do something about this specific line of code>
   Err.Clear()
End If

Oder Sie können Folgendes sehen:

Sub DoSomething

   On Error Goto Handler1
   <do something that causes an error>

   On Error Goto Handler2
   <do something that may cause an error>

   Exit Sub

   Handler1:
   <log error or something>
   Resume Next

   Handler2:
   <log error or something>
   Resume Next

End Sub  

Aber im alten VB6 -Code werden Sie dies wahrscheinlich auch sehen ...

Sub PerformThis
On Error Resume Next

End Sub

Unabhängig davon ist es ziemlich einfach, diese Fälle in den Versuch zu konvertieren ... Wenn Sie einen Fehler mit einem schnellen "Inline" versenken müssen.

try { _objectinfo.Add(_object.attribute1); } catch (Exception _e) { }

Sie können den Versuch auch auf die Anrufroutine erhöhen, indem Sie den Code in eine Unterprogramme einkapseln ... wenn Sie also das gesamte Unterroutine versenken müssen, tun Sie dies ...

try { PerformAction(); } catch (Exception _e) { }

Tun Sie dies in dem Fall, in dem PerformAction () Subroutine als nächstes oben im Code einen Fehler -Lebenslauf enthält

Viel Glück...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top