Laden...

Alternative zu goto

Erstellt von antoschka vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.991 Views
A
antoschka Themenstarter:in
371 Beiträge seit 2007
vor 15 Jahren
Alternative zu goto

Hallo,

da ich goto nur in switches verwenden und sonst eisern diesem unheilvollen Befehl abschwöre suche ich nach einer Alternative für folgendes Szenario wo cih dummerweise immer wieder auf goto zurück komme. Irgendwie stehe ich auf dem Schlauch:
Ich habe ein Feld "myField" vom Type Class1.
Diesem wird in einem ersten Befehl ein Wert zugeordnet oder nicht.
Falls nicht kann gleich zu Anweisung finalCommand gesprungen werden.
Falls ein Wert zugeordnet wurde, werden wertere PrüfungEN absolviert, bei jeder trifft die gleich logik zu: Falls myField == null ist prüfe nicht weiter sondern gehe gleich zu finalCommand. Wenn myField bis zum Schluss nicht null wird muss finalCommand nicht ausgeführt werden.

ich könnte jetzt in den setter ein Event rein packen und mit einem Thread und Exceptions auf "==null". Das wäre aber mit Kanonen auf Spatzen geschossen, oder?

Zur Zeit prüfe ich vor jeder Prüfung ob myField1 ist. Ich glaube das ist aber nicht sehr performant, da der Code sehr häufig (!) durchlaufen wird und es nicht selten vorkommt, dass schon nach der ersten Anweisung myField == null ist und somit die nachfolgenden Prüfungen gar nicht in betracht kommen.
EIne geschachtelte if sieht auch böse aus, da es sich wirklich um einige Prüfung handelt.
Pseudo Code
myField = firstCommand;
if (myField != null) doSomethingWithMyField1(myField);
else goto finalCommand;
if (myField != null) doSomethingWithMyField2(myField);
else goto finalCommand;
if (myField != null) doSomethingWithMyField3(myField);
else goto finalCommand;
if (myField != null) doSomethingWithMyField4(myField);
else goto finalCommand;
finalCommand: myField;
Hat jemand eine andere Idee? Besten Dank für Euer Feedback antoschka

3.430 Beiträge seit 2007
vor 15 Jahren

Hallo antoschka,

du könntest das auch so machen:


			for (int i = 1; i <= 4; i++)
			{
				if (myField != null)
				{
					switch (i)
					{
						case 1:
							doSomethingWithMyField1(myField);
							break;
						case 2:
							doSomethingWithMyField2(myField);
							break;
						case 3:
							doSomethingWithMyField3(myField);
							break;
						case 4:
							doSomethingWithMyField4(myField);
							break;
					}
				}
				else
				{
					break;
				}
			}
			finalCommand();


Syntaxfehler nicht ausgeschlossen, da nur hier gecoded 🙂

Gruss
Michael

O
778 Beiträge seit 2007
vor 15 Jahren

du könntest auch einfach alle Methoden ausführen und in der jeweils ersten Zeile der Methoden sagen, dass die sich beenden sollen, wenn das übergebene Objekt null ist. Das würde diese Methoden gleichzeitig robuster machen.

Alternativ kannst du natürlich auch ewig lange ineinander verschachtelte if-Schleifen machen.

Sinnvoll würde ich auch finden, wenn die Methoden einen Boolean Rückgabewert hätten, der angibt, ob das Ganze was gebracht hat oder nicht. Damit kannst du den ganzen Scheiß in eine einzige if-Schleife setzen.

3.430 Beiträge seit 2007
vor 15 Jahren

Hallo Onlinegurke,

if-Schleife http://www.if-schleife.de/

🙂

Gruss
Michael

A
antoschka Themenstarter:in
371 Beiträge seit 2007
vor 15 Jahren

Hallo,

ich glaube Michaels Lösung nehme ich.
@ onlineGurke: Mit Deiner Lösung hätte ich ja wieder das Problem, dass ich alle Prüfungen durchlaufen muss. Naja und mit der geschachtelten Schleife kann ich mich wie gesagt nicht anfreunden.

Besten Dank für Euer Feeback

antoschka

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo antoschka,

pack deinen Code in einen try/finally-Block und verwende statt goto return.

herbivore

5.742 Beiträge seit 2007
vor 15 Jahren

pack deinen Code in einen try/finally-Block und verwende statt goto return.

Auch wenn es unwahrscheinlich ist:
Sobald in dem try-Block eine Exception geworfen wird, wird der finally Block trotzdem ausgeführt. Das wird ziemlich sicher zu einer weiteren Exception führen, wenn innerhalb des try-Blocks das Objekt vorbereitet werden sollte.
Allerdings ist der "wahre Fehler" dann nur noch schwer zu finden, da die eigentliche Exception verschluckt wird.

Besser ist es da, den Code in eine Methode auszulagern und mit return zu arbeiten. Dann wird innerhalb der Methode das Objekt vorbereitet und nach Ausführung der Methode kann man sicher sein, dass es vorbereitet ist.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo winSharp93,

dass man in finally damit rechnen muss, dass man aufgrund einer Exception dort hingekommen ist, habe ich vorausgesetzt. Das war vielleicht etwas leichtfertig, aber anderseits aufgrund des try's eigentlich auch klar.

Das mit der Auslagerung in eine extra Methode ist natürlich auch eine Möglichkeit, wobei die Änderung der Code-Struktur etwas größer. Aber natürlich bestehen hinsichtlich der Exceptions die von dir genannten Vorteile.

herbivore

U
1.688 Beiträge seit 2007
vor 15 Jahren

Hallo,

ich versteh zwar noch nicht ganz, wo das Problem liegt, da ich nicht sehe, wo myField geändert wird. Vorausgesetzt aber, dass es nur in Deinem Pseudocode fehlt (ref?), wäre auch die folgende Abwandlung von michlGs Vorschlag denkbar (ich mag selten switch/case, die sind je nach Compiler vor allem für die letzten Alternativen immer sehr langsam)


  for (int i=0; myField!=null && i<4; i++) {
    doSomethingWithMyField[i](ref myField);
  }
  finalCommand();

wobei doSomethingWithMyField ein Array von entsprechenden Delegates ist, das ein Mal zu initialisieren ist.

Um die Prüfung auf null wirst Du nicht herumkommen. Wobei mir eigentlich meist die invertierte Prüfung lieber ist - in Deinem Pseudo-Code also:

if (myFieldnull) goto finalCommand;
dosomethingwithmyfield(myField);
if (myField
null) ...