C # 4.0: Kann ich einen TimeSpan als optionalen Parameter mit einem Standardwert verwenden?
Beide generieren einen Fehler zu sagen, Sie muss eine compile-Zeit-Konstante:
void Foo(TimeSpan span = TimeSpan.FromSeconds(2.0))
void Foo(TimeSpan span = new TimeSpan(2000))
Zuerst von all, kann mir jemand erklären, warum diese Werte können nicht ermittelt werden bei der Kompilierung? Und gibt es eine Möglichkeit, geben Sie einen Standardwert für eine optionale TimeSpan-Objekt?
Kommentar zu dem Problem
Nicht im Zusammenhang zu dem, was Sie Fragen, aber bewusst sein, dass
new TimeSpan(2000)
bedeutet nicht 2000 Millisekunden, es bedeutet 2000 "Zecken", die bei 0,2 Millisekunden, oder eine der 10.000 te von zwei Sekunden. InformationsquelleAutor der Frage Mike Pateras | 2010-01-30
Du musst angemeldet sein, um einen Kommentar abzugeben.
Umgehen kannst du dies sehr leicht, indem Sie Ihre Unterschrift.
Sollte ich umständlich - der Grund, die Ausdrücke in deinem Beispiel sind keine compile-Zeit-Konstanten ist da beim kompilieren, kann der compiler nicht einfach ausführen Zeitspanne.FromSeconds(2.0) stick und die bytes des Ergebnisses in Ihrer kompilierten code.
Betrachten Sie beispielsweise, wenn Sie versucht, auf DateTime.Jetzt statt. Der Wert von DateTime.Jetzt ändert sich jedes mal, wenn es ausgeführt wird. Oder angenommen, TimeSpan.FromSeconds berücksichtigte die Schwerkraft. Es ist ein absurdes Beispiel, aber die Regeln des compile-Zeit-Konstanten nicht machen besonderen Fällen, nur weil wir zufällig wissen, dass TimeSpan.FromSeconds deterministisch ist.
InformationsquelleAutor der Antwort Josh
Meine VB6-Erbe macht mich unwohl mit der Idee, unter Berücksichtigung der "null-Wert" und "fehlenden Wert" zu entsprechen. In den meisten Fällen, ist es wahrscheinlich in Ordnung, aber haben Sie vielleicht ein unbeabsichtigter Nebeneffekt, oder Sie schlucken konnte eine außergewöhnliche Bedingung (zum Beispiel, wenn die Quelle der
span
ist eine Eigenschaft oder variable, sollte nicht null sein, sondern ist).Ich würde daher die überlastung der Methode:
InformationsquelleAutor der Antwort phoog
Dieser gut funktioniert:
void Foo(TimeSpan span = default(TimeSpan))
InformationsquelleAutor der Antwort Elena Lavrinenko
Die Werte, die verwendet werden kann als Standard-Wert sind die gleichen wie die verwendet werden können für ein Attribut-argument. Der Grund ist, dass default-Werte kodiert sind, in Metadaten innerhalb der
DefaultParameterValueAttribute
.Warum kann es nicht bestimmt werden zur compile-Zeit. Die Werte und Ausdrücke, die über solche Werte erlaubt zur Kompilierzeit ist aufgeführt in der offiziellen Sprache C# spec:
Art
TimeSpan
paßt in keine dieser Listen und kann daher nicht verwendet werden, als eine Konstante.InformationsquelleAutor der Antwort JaredPar
zur Verfügung gestellt
default(TimeSpan)
ist kein Gültiger Wert für die Funktion.Oder
zur Verfügung gestellt
new TimeSpan()
ist kein Gültiger Wert.Oder
Diese sollten besser sein, in Anbetracht Chancen
null
Wert einen gültigen Wert für die Funktion sind selten.InformationsquelleAutor der Antwort nawfal
TimeSpan
ist ein besonderer Fall für dieDefaultValueAttribute
und ist angegeben mit beliebigen string, der geparst werden können, die über dieTimeSpan.Parse
Methode.InformationsquelleAutor der Antwort dahall
Andere Antworten haben große Erklärungen, warum ein optionaler parameter, der nicht einen dynamischen Ausdruck. Aber, um zu erzählen, Standard-Parameter Verhalten sich wie die compile-Zeit-Konstanten. Das bedeutet, dass der compiler muß in der Lage sein, um Sie zu bewerten und kommen mit einer Antwort. Es gibt einige Leute, die wollen C# hinzufügen der Unterstützung für compiler-Evaluierung dynamischer Ausdrücke bei der Begegnung mit Konstanten Deklarationen—diese Art von feature wäre in Bezug auf Kennzeichnung, Methoden der "reinen", aber das ist nicht eine Realität, jetzt und vielleicht nie werden.
Eine alternative für die Verwendung einer C# - Standard-parameter für eine solche Methode wäre, um die Muster am Beispiel von
XmlReaderSettings
. In diesem Muster definieren Sie eine Klasse mit einer parameterlosen Konstruktor und öffentlich beschreibbaren Eigenschaften. Dann ersetzen Sie alle Optionen mit Standardwerten in Ihre Methode mit einem Objekt von diesem Typ. Auch machen Sie dieses Objekt, optional durch die Angabe eines default vonnull
. Zum Beispiel:Aufrufen, verwenden Sie diesen seltsamen syntax für das instanzieren und zuweisen von Eigenschaften alle in einem Ausdruck:
Nachteile
Dies ist ein wirklich schwerwiegend Ansatz zur Lösung dieses Problems. Wenn Sie schreiben einen quick-and-dirty interne Schnittstelle und machen Sie die
Zeit
null-Werte zulässt und die Behandlung von null-wie Ihre gewünschte Standard-Wert würde funktionieren, nicht stattdessen.Auch, wenn Sie eine große Anzahl von Parametern oder sind dem Aufruf der Methode in einer engen Schleife, wird dies den overhead der class-Instanzen. Natürlich, wenn der Aufruf einer solchen Methode in eine Endlosschleife geraten, könnte es natürlich sein und auch sehr einfach wiederverwenden eine Instanz der
FooSettings
Objekt.Vorteile
Wie ich bereits im Kommentar im Beispiel, ich denke, dieses Muster ist für den öffentlichen APIs. Hinzufügen von Eigenschaften zu einer Klasse ist ein non-breaking ABI ändern, so können Sie neue optionale Parameter, ohne die änderung der Signatur der Methode, die dieses Muster verwenden—geben mehr kürzlich kompilierten code mehr Optionen während der weiteren Unterstützung der alten kompilierten code mit keine zusätzliche Arbeit.
Auch, weil C#'s gebaut in Standard-Parameter der Methode behandelt werden als compile-Zeit-Konstanten und gebacken in der callsite, Standard-Parameter wird nur verwendet, indem der code einmal kompiliert wird. Durch instanziieren eines einstellungsobjekts, die Anrufer lädt dynamisch die default-Werte, die beim Aufruf Ihrer Methode. Dies bedeutet, dass Sie aktualisieren können Standardeinstellungen ändern Sie einfach Ihre Einstellungen. Klasse. So, dieses Muster können Sie die Standardwerte ändern ohne neu kompilieren zu müssen Anrufer zu sehen, die neuen Werte, falls dies gewünscht wird.
InformationsquelleAutor der Antwort binki
Mein Vorschlag:
BTW
TimeSpan.FromSeconds(2.0)
nicht gleichnew TimeSpan(2000)
- der Konstruktor nimmt Zecken.InformationsquelleAutor der Antwort tymtam