Ich habe eine Klasse Animal
und ihre Unterklasse Dog
. Ich finde mich oft dabei, die folgenden Zeilen zu codieren:
if (animal is Dog)
{
Dog dog = animal as Dog;
dog.Name;
...
}
Für die Variable Animal animal;
.
Gibt es eine Syntax, mit der ich etwas schreiben kann wie:
if (Dog dog = animal as Dog)
{
dog.Name;
...
}
c#
casting
if-statement
Michael
quelle
quelle
bool
Zustand?null
! =false
In C #; C # erlaubt nur tatsächliche Bools oder Dinge, die implizit unter bestimmtenif
Bedingungen in Bools konvertierbar sind. Weder Nullen noch einer der Integer-Typen können implizit in Bools konvertiert werden.Antworten:
Die folgende Antwort wurde vor Jahren geschrieben und im Laufe der Zeit aktualisiert. Ab C # 7 können Sie den Mustervergleich verwenden:
Beachten Sie, dass dies
dog
nach derif
Anweisung noch im Geltungsbereich liegt , aber nicht definitiv zugewiesen ist.Nein, gibt es nicht. Es ist jedoch idiomatischer, dies zu schreiben:
Angesichts der Tatsache, dass "wie folgt von if" fast immer auf diese Weise verwendet wird, ist es möglicherweise sinnvoller, dass es einen Bediener gibt, der beide Teile auf einmal ausführt. Dies ist derzeit nicht in C # 6 enthalten, kann jedoch Teil von C # 7 sein, wenn der Mustervergleichsvorschlag implementiert ist.
Das Problem ist, dass Sie im Bedingungsteil einer Anweisung 1 keine Variable deklarieren können . Der nächste Ansatz, den ich mir vorstellen kann, ist folgender:
if
Das ist nur böse ... (Ich habe es gerade versucht und es funktioniert. Aber bitte, bitte tu das nicht. Oh, und du kannst natürlich die
dog
Verwendung deklarierenvar
.)Natürlich können Sie eine Erweiterungsmethode schreiben:
Dann nenne es mit:
Alternativ können Sie beide kombinieren:
Sie können auch eine Erweiterungsmethode ohne Lambda-Ausdruck sauberer als die for-Schleife verwenden:
Dann:
1 Sie können Werte in Anweisungen zuweisen
if
, obwohl ich dies selten tue. Das ist jedoch nicht dasselbe wie das Deklarieren von Variablen. Es ist nicht sonderlich ungewöhnlich für mich, dieswhile
beim Lesen von Datenströmen zu tun . Beispielsweise:Heutzutage bevorzuge ich normalerweise die Verwendung eines Wrappers, mit dem ich ihn verwenden kann,
foreach (string line in ...)
aber ich betrachte das Obige als ein ziemlich idiomatisches Muster. Es ist normalerweise nicht schön, Nebenwirkungen innerhalb einer Bedingung zu haben, aber die Alternativen beinhalten normalerweise eine Codeduplizierung, und wenn Sie dieses Muster kennen, ist es einfach, es richtig zu machen.quelle
EVIL EVIL EVIL
, aber ich bin nicht positiv.AsEither(...)
. Ich denke, sie ist etwas klarer alsAsIf(...)
, damit ich schreiben kannmyAnimal.AsEither(dog => dog.Woof(), cat => cat.Meeow(), unicorn => unicorn.ShitRainbows())
.Wenn dies
as
fehlschlägt, wird es zurückgegebennull
.quelle
if
Anweisung und nicht im äußeren Bereich erstellen .if
kann ein booles Ergebnis und eine Zuordnung haben.Dog dog; if ((dog = animal as Dog) != null) { // Use Dog }
Damit wird die Variable jedoch immer noch in den äußeren Bereich eingeführt.Sie können der Variablen den Wert zuweisen, solange die Variable bereits vorhanden ist. Sie können die Variable auch so erweitern, dass dieser Variablenname später in derselben Methode erneut verwendet werden kann, wenn dies ein Problem darstellt.
unter der Annahme
erhält Ausgabe:
Das Muster der Variablenzuweisung im Test wird auch beim Lesen von Byteblöcken aus Streams verwendet, zum Beispiel:
Das oben verwendete Muster des variablen Gültigkeitsbereichs ist jedoch kein besonders verbreitetes Codemuster, und wenn ich sehen würde, dass es überall verwendet wird, würde ich nach einer Möglichkeit suchen, es umzugestalten.
quelle
Es wird wahrscheinlich in C # 6.0 sein. Diese Funktion wird als "Deklarationsausdrücke" bezeichnet. Sehen
https://roslyn.codeplex.com/discussions/565640
für Details.
Die vorgeschlagene Syntax lautet:
Allgemeiner ist das vorgeschlagene Merkmal, dass eine lokale Variablendeklaration als Ausdruck verwendet werden kann . Diese
if
Syntax ist nur eine nette Folge der allgemeineren Funktion.quelle
Try*
(zTryParse
. B. ). Diese Funktion macht solche Aufrufe nicht nur zu einem einzigen Ausdruck (wie sie sein sollten, IMO), sondern ermöglicht auch ein saubereres Scoping solcher Variablen. Ich bin begeistert davon, dass derout
Parameter einerTry
Methode auf ihre Bedingungen festgelegt wird. Dies macht es schwieriger, bestimmte Arten von Fehlern einzuführen.Eine der Erweiterungsmethoden, die ich häufig schreibe und verwende *, ist
Welches könnte in dieser Situation als verwendet werden
Und dann
name
ist der Name des Hundes (wenn es ein Hund ist), sonst null.* Ich habe keine Ahnung, ob dies performant ist. Es ist nie zu einem Engpass bei der Profilerstellung gekommen.
quelle
Hier gegen den Strich gehen, aber vielleicht machst du es überhaupt falsch. Das Überprüfen des Objekttyps ist fast immer ein Codegeruch. Haben in Ihrem Beispiel nicht alle Tiere einen Namen? Rufen Sie dann einfach Animal.name auf, ohne zu prüfen, ob es sich um einen Hund handelt oder nicht.
Alternativ können Sie die Methode invertieren, sodass Sie eine Methode für Animal aufrufen, die je nach dem konkreten Typ des Tieres etwas anderes tut. Siehe auch: Polymorphismus.
quelle
Kürzere Aussage
quelle
Hier ist ein zusätzlicher schmutziger Code (allerdings nicht so schmutzig wie der von Jon :-)), der von der Änderung der Basisklasse abhängt. Ich denke, es fängt die Absicht ein, während es vielleicht den Punkt verfehlt:
quelle
Wenn Sie mehrere As-Ifs nacheinander ausführen müssen (und die Verwendung von Polymorphismus keine Option ist), sollten Sie ein SwitchOnType- Konstrukt verwenden.
quelle
Das Problem (mit der Syntax) liegt nicht bei der Zuweisung, da der Zuweisungsoperator in C # ein gültiger Ausdruck ist. Es ist vielmehr mit der gewünschten Deklaration, da Deklarationen Aussagen sind.
Wenn ich solchen Code schreiben muss, schreibe ich den Code manchmal (abhängig vom größeren Kontext) wie folgt:
Es gibt Vorteile mit der obigen Syntax (die der angeforderten Syntax nahe kommt), weil:
dog
außerhalb derif
wird in einem Compiler - Fehler zur Folge haben, da sie keinen Wert an anderer Stelle zugeordnet ist. (Das heißt, nichtdog
anderswo zuweisen .)if/else if/...
(Es gibt nur so vieleas
wie erforderlich, um einen geeigneten Zweig auszuwählen; dies ist der große Fall, in dem ich ihn in dieser Form schreibe, wenn ich muss.)is/as
. (Aber auch mitDog dog = ...
Form gemacht.)Um sich wirklich
dog
vom Rest der Welt zu isolieren , kann ein neuer Block verwendet werden:Viel Spaß beim Codieren.
quelle
Sie können so etwas verwenden
// Variable deklarieren bool temp = false;
quelle
Eine weitere böse Lösung mit Erweiterungsmethoden :)
Ich persönlich bevorzuge den sauberen Weg:
quelle
Eine if-Anweisung lässt das nicht zu, eine for-Schleife jedoch.
z.B
Falls die Funktionsweise nicht sofort ersichtlich ist, finden Sie hier eine schrittweise Erklärung des Prozesses:
Iteration.
quelle
quelle
IDK, wenn dies jemandem hilft, aber Sie können jederzeit versuchen, Ihre Variable mit TryParse zuzuweisen. Hier ist ein Beispiel:
Die Gesamt Variable würde , bevor Ihre if - Anweisung deklariert werden.
quelle
Ich habe gerade die if-Anweisung eingefügt, um eine Codezeile zu erstellen, die so aussieht, wie Sie interessiert sind. Sie hilft nur dabei, den Code zu komprimieren, und ich fand ihn besser lesbar, insbesondere beim Verschachteln von Zuweisungen:
quelle
Ich weiß, dass ich zu spät zur Party komme, aber ich dachte, ich würde meine eigene Problemumgehung für dieses Dilemma veröffentlichen, da ich es hier (oder sonstwo) noch nicht gesehen habe.
Damit können Sie Dinge tun wie:
WICHTIGER HINWEIS: Wenn Sie TryAs () über eine Schnittstelle verwenden möchten, MUSS diese Schnittstelle IAble erben.
Genießen! 🙂
quelle