Frage

Diese Frage ist ein Follow-up von Wie um anzuzeigen, dass ein Methode war nicht erfolgreich . Die xxx () Tryxxx () Muster ist etwas, das in vielen Bibliotheken sehr nützlich sein kann. Ich frage mich, was der beste Weg ist, um beiden Implementierungen anzubieten, ohne meinen Code zu duplizieren.

Was ist das Beste:

public int DoSomething(string a)
{
     // might throw an exception
}
public bool TrySomething(string a, out result)
{
    try
    {
        result = DoSomething(a)
        return true;
    }
    catch (Exception)
    {
        return false;
    }

oder

public int DoSomething(string a)
{
     int result;
     if (TrySomething(a, out result))
     {
         return result;
     }
     else
     {
         throw Exception(); // which exception?
     }
}
public bool TrySomething(string a, out result)
{
    //...
}

würde ich instinktiv davon aus, dass das erste Beispiel mehr korrekt ist (Sie genau wissen, welche Ausnahme passiert ist), konnte aber die try / catch nicht zu teuer sein? Gibt es eine Möglichkeit, die Ausnahme im zweiten Beispiel zu fangen?

War es hilfreich?

Lösung

Machen TrySomething nur fangen und schlucken die Ausnahme ist eine wirklich schlechte Idee. Die Hälfte der Punkt des TryXXX Musters ist es, die Leistungseinbußen von Ausnahmen zu vermeiden.

Wenn Sie nicht viele Informationen in Ausnahme benötigen, können Sie die Methode DoSomething machen nur TrySomething anrufen und eine Ausnahme auslösen, wenn es fehlschlägt. Wenn Sie Details in der Ausnahme benötigen, können Sie etwas aufwändigere benötigen. Ich habe nicht abgelaufen ist, wo der Großteil der Performance-Einbußen von Ausnahmen ist - wenn es das Werfen ist nicht das Erstellen, Sie könnten eine private Methode schreiben, die eine ähnliche Signatur TrySomething hatten, die aber wieder eine Ausnahme oder null:

public int DoSomething(string input)
{
    int ret;
    Exception exception = DoSomethingImpl(input, out ret);
    if (exception != null)
    {
        // Note that you'll lose stack trace accuracy here
        throw exception;
    }
    return ret;
}

public bool TrySomething(string input, out int ret)
{
    Exception exception = DoSomethingImpl(input, out ret);
    return exception == null;
}

private Exception DoSomethingImpl(string input, out int ret)
{
    ret = 0;
    if (input != "bad")
    {
        ret = 5;
        return null;
    }
    else
    {
        return new ArgumentException("Some details");
    }
}

Zeit dies, bevor Sie zu begehen aber!

Andere Tipps

ich in der Regel dieses Muster verwenden. Hängt davon ab, wie das interne Verfahren implementiert, ob nicht der Sinn macht. Wenn Sie bedingte catch-Blöcke zu verwenden haben kann es ein bisschen unangenehm werden ...

public object DoSomething(object input){
  return DoSomethingInternal(input, true);
}

public bool TryDoSomething(object input, out object result){
  result = DoSomethingInternal(input, false);
  return result != null;
}

private object DoSomethingInternal(object input, bool throwOnError){
  /* do your work here; only throw if you cannot proceed and throwOnError is true */
}

Das erste Beispiel ist richtig, wenn Sie nur die Ausnahme fangen gehen und nichts zu tun, aber return false mit ihm.

Sie könnten TrySomething ändern wie unten aussehen.

public bool TrySomething(string a, out result, bool throwException)
{
  try
  {
    // Whatever
  }
  catch
  {
    if(throwException)
    {
      throw;
    }
    else
    {
      return false;
    }
  }

}

public bool TrySomething(string a, out result)
{
  return TrySomething(a, out result, false);
}

So DoSomething würde wie folgt aussehen

public int DoSomething(string a)
{
  int result;

  // This will throw the execption or 
  // change to false to not, or don't use the overloaded one.
  TrySomething(a, out result, true) 

  return result;      
}

Wenn Sie nicht TrySomething mit ThrowException der Öffentlichkeit ausgesetzt wollen, so können Sie es ein privates Mitglied machen.

Ausnahmen könnte teuer und man konnte einige RegEx tun auf der Saite Kontrolle zu verhindern, dass ein geworfen. Es hängt davon ab, was Sie zu tun versuchen.

Unter der Annahme, diese C # ist, würde ich das zweite Beispiel sagen

public bool TrySomething(string a, out result)
{
    try
    {
        result = DoSomething(a)
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}

Es ahmt die in int.TryParse(string s, out int result) gebaut, und meiner Meinung nach seine besten im Einklang mit der Sprache / Umgebung zu bleiben.

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