2009-03-11 4 views
47

Ich habe eine String-Eigenschaft, die eine maximale Länge erfordert, da die Daten mit einer Datenbank verknüpft sind. Welche Ausnahme sollte ich auslösen, wenn der Anrufer versucht, eine Zeichenfolge zu setzen, die diese Länge überschreitet?Welche Ausnahme von einem Property Setter zu werfen?

Zum Beispiel dieses C# -Code:

public string MyProperty 
{ 
    get 
    { 
     return _MyBackingField; 
    } 
    set 
    { 
     if (value.Length > 100) 
      throw new FooException("MyProperty has a maximum length of 100."); 

     _MyBackingField = value; 
    } 
} 

ich als ArgumentException, aber es scheint einfach nicht richtig. Technisch ist es eine Funktion - MyProperty_set(string value) - so kann ein Fall für ArgumentException gemacht werden, aber es wird nicht als eine Funktion für die Augen des Verbrauchers aufgerufen - es ist auf der rechten Seite eines Zuweisungsoperators.

Diese Frage könnte wahrscheinlich auch auf alle Arten von Datenvalidierung ausgedehnt werden, die in Property Settern gemacht werden, aber ich bin besonders an dem obigen Fall interessiert.

Antwort

44

Werfen Sie einen Blick durch mscorlib.dll mit Reflektor, in einer ähnlichen Situation wie System.String.StringBuilder.Capacity Microsoft verwenden ArgumentOutOfRangeException() ähnlich:

public int PropertyA 
{ 
    get 
    { 
     return //etc... 
    } 
    set 
    { 
     if (condition == true) 
     { 
      throw new ArgumentOutOfRangeException("value", "/* etc... */"); 
     } 
     // ... etc 
    } 
} 
+1

BTW, wirft Mono ein Argument in diesem Fall ... –

+13

„ArgumentOutOfRangeException - Die Ausnahme, die ausgelöst wird, wenn der Wert eines Arguments außerhalb des zulässigen Wertebereiches ist, wie durch der definierte aufgerufene Methode " .... imo, sollte Mono ihren Code reparieren. –

-1

Sie können InvalidOperationException verwenden. Das ist ein Kompromiss. Ich würde auch keine ArgumentException verwenden.

16

Für mich Argument (oder ein Kind) macht mehr Sinn, weil das von Ihnen angegebene Argument (value) nicht gültig ist, und dafür wurde ArgumentException erstellt.

10

Ich würde keine Ausnahme überhaupt werfen. Stattdessen würde ich eine Zeichenfolge beliebiger Länge zulassen und dann eine separate "Validate" -Methode für die Klasse verwenden, die vor dem Speichern aufgerufen wird. Es gibt eine Reihe von Szenarien, insbesondere wenn Sie Datenbindungen verwenden, bei denen das Auslösen von Ausnahmen von Eigenschaften-Setter Sie in Unordnung bringen kann.

Das Problem mit dem Auslösen von Ausnahmen von Property Settern ist, dass Programmierer vergessen, sie zu fangen. Es hängt davon ab, wie sauber Sie die Daten erwarten, die Sie erhalten. In diesem Fall würde ich erwarten, dass lange String-Längen üblich und nicht außergewöhnlich sind, und als solche eine Ausnahme verwenden würde, wäre "Flusssteuerung mit Ausnahmen".

Um von der Design Guidelines for Developing Class Libraries Microsoft zu zitieren:

Keine Ausnahmen für den normalen Fluss Kontrolle verwenden, wenn möglich. Außer für Systemausfälle und Operationen mit potenziellen Race-Bedingungen, sollten Framework-Designer APIs so entwerfen, dass Benutzer Code schreiben können, der nicht Ausnahmen wirft. Sie können beispielsweise eine Möglichkeit bereitstellen, die Vorbedingungen vor dem Aufrufen eines Mitglieds zu überprüfen, damit Benutzer Code schreiben können, der keine Ausnahmen auslöst.

+4

Während ich persönlich überhaupt nicht zustimme (Validation ist doch der Job des Setter - sonst hat es keinen Sinn, etwas anderes zu haben als simples field = value; return field; getters/setter - ich mag es, dass Sie den Punkt erhöhen DataBinding, die in der Tat Sie in Unordnung bringen kann. –

+1

Exception warf in Property Setter ist OK zu tun, ich würde keine Ausnahmen in Eigenschaft getters obwohl. –

+0

Verzögern das Werfen einer Ausnahme wird nicht zulassen, dass Sie die infractor zu fangen. Wenn ein Programmierer vergisst, eine Ausnahme zu fangen, springt er auf sein Gesicht, anstatt versehentlich zu sprudeln – Trap

6

Denken Sie daran, wie viele Probleme in der Informatik gelöst werden, indem Sie ein zusätzliches Maß an Indirektion hinzufügen?

Ein Ansatz wäre, einen neuen Typ zu erstellen, FixedLengthString, sagen wir. Es wären Instanzen von , die Typ, die Längen von Zeichenfolgen validieren, die sie initialisiert werden - mit einem Konvertierungsoperator, Typ Konvertierung von einer einfachen Zeichenfolge zu tun.Wenn Ihr Eigenschaften-Setter einen solchen Typ wie sein Argument annimmt, wird jeder Verstoß zu einer Typkonvertierungsausnahme anstelle einer Argument-/Eigenschaftenausnahme.

In der Praxis würde ich das selten tun. Es riecht etwas nach OO zu weit - aber in einigen Fällen kann es eine nützliche Technik sein, daher erwähne ich es hier aus Gründen der Vollständigkeit.

+2

Wie würden Sie mit der Übergabe eines FixedLengthString-Satzes von maximal 100 Zeichen an eine Eigenschaft umgehen, für die ein FixedLengthString-Satz von maximal 50 Zeichen erforderlich war? –

-2

Versuchen Sie, vorhandene Ausnahmen wo immer möglich zu verwenden. In diesem Fall verwenden Sie InvalidOperationException, weil der eingehende Wert das Objekt in einen inkonsistenten Zustand bringt. Benutzerdefinierte Ausnahmen können erstellt werden, wenn eine bestimmte Behandlung mit der benutzerdefinierten Ausnahme erforderlich ist. In diesem Fall wird nur eine Ausnahme mit Text ausgelöst. Verwenden Sie daher die InvalidOperationException.

Wenn die InvalidOperationException ausgelöst wird, wird der Wert angezeigt, der an diesen Setter übergeben wurde.

+0

Natürlich können Sie das Beste aus beiden Welten haben und Ihren eigenen Ausnahmetyp erstellen, der sich beispielsweise von InvalidOperationException ableitet. Natürlich zahlen Sie immer noch etwas zusätzlichen Code und Komplexität. Es ist eine kleine Kosten, aber nach dem Wiegen können Sie es immer noch nicht wert – philsquared

+2

InvalidOperationException sollte in diesem Fall nicht ausgelöst werden. Was falsch ist, ist der Wert, nicht der Vorgang der Einstellung des Wertes. – Trap

5
public IPAddress Address 
{ 
    get 
    { 
     return address; 
    } 
    set 
    { 
     if(value == null) 
     { 
      throw new ArgumentNullException("value"); 
     } 
     address = value; 
    } 
} 

über MSDN

+0

Guter Punkt, obwohl dies für den Nullfall spezifisch ist. Es unterstützt jedoch die Verwendung der 'ArgumentException'-Reihe, also +1 für die Referenz. –