Bedingungslose Konsolenapp - wie lass ich das Programm bis zum Benutzerendewunsch laufen?

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 29 Antworten in diesem Thema. Der letzte Beitrag () ist von Gregor Jasinski.

    Bedingungslose Konsolenapp - wie lass ich das Programm bis zum Benutzerendewunsch laufen?

    Hallo zusammen.

    Gleich vorab: Wer in folgendem Vorhaben keinen Sinn erkennt, dem möge bitte bewusst sein, dass es hier um eine (für mich) experimentelle Programmierform geht. Mir ist bewusst, dass das Folgende ein ziemliches Umdenken der gewohnten Programmierpraxis darstellt.

    Im Zuge der Entwicklung eines kleinen Konsolentools habe ich heute mich mal darin geübt, das Programm ohne Ifs oder Bools, aber zumindest mit einem Benutzermenü zu entwickeln. Der User kann sich also über die Eingabe aussuchen, was passieren soll:

    Quellcode

    1. 1.: Daten sammeln und mit alten Daten vergleichen
    2. 2.: aktuelle Daten merken und alte verwerfen
    3. 3.: Programm beenden


    Das Menü und die Verarbeitung der Benutzereingabe ohne Ifs oder Select Case zu machen, habe ich geschafft, auch die Aufgaben selbst ohne Booleans und Ifs etc durchzuführen, konnte ich umsetzen.
    Nur das Hauptmenü macht mir Schwierigkeiten.

    Ich habe bisher zwei Ansätze:
    1. Eine For-Schleife, die von 1 bis 1 geht und wenn das Programm aufgrund der Benutzerauswahl nicht beendet werden soll, wird die Zählervariable wieder auf Null gesetzt. Mir ist klar, dass das irgendwo doch eine Bedingung ist.

    VB.NET-Quellcode

    1. Private MainLoopCounter As Integer
    2. Sub Main()
    3. CreatePossibleUserChoices()
    4. For MainLoopCounter = 1 To 1
    5. ShowMenu()
    6. SelectSubRoutineAccordingToUserInput()
    7. ExecuteSelectedSubRoutine()
    8. ShowFinalTextAfterExecution()
    9. PossiblyResetMainLoopCounter()
    10. Next
    11. End Sub


    2. Am Ende der Main-Methode dieselbige einfach nochmal aufrufen, wenn das Programm nicht beendet werden soll. Wird aber beim 1000. Mal oder irgendwann eben zu nem stack overflow führen.

    Welche Möglichkeiten gäbe es noch? Neustart der App, wenn das Programm nicht endgültig beendet werden soll, käme mir etwas rabiat vor.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Wäre das etwas?

    VB.NET-Quellcode

    1. Private ExitFlag As Boolean
    2. Sub Main(args As String())
    3. While Not ExitFlag
    4. End While
    5. End Sub

    Dann einfach ExitFlag auf True setzen, wenn der User das will.


    Nein, ist ja eine Bedingung. Das ist ja richtig was zum knobeln.

    Edit:
    @VaporiZed
    Da ist mir ein totaler Holzhammer eingefallen: :D

    VB.NET-Quellcode

    1. Imports System
    2. Module Program
    3. Sub Main(args As String())
    4. 0:
    5. Try
    6. StayaliveTest()
    7. GoTo 0
    8. Catch ex As Exception
    9. End Try
    10. End Sub
    11. Private Sub StayaliveTest()
    12. Console.WriteLine("Enter illegal Value for Datetime Konstruktor to exit")
    13. Dim x As DateTime = New DateTime(Console.ReadLine())
    14. End Sub
    15. End Module


    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „DTF“ ()

    Also wenn du wirklich keine If-Abfragen oder Booleans nutzen möchtest, dann fällt mir auch nur so eine Grütze die @DTFs Antwort ein...

    Also wie ich das in C/++ machen würde, wüsste ich. Da würde ich mir stumpf von allen Funktionen die Adressen holen und einfach solange mit ​setjmp/longjmp hin- und herspringen.
    Irgendwann kann man halt einfach die Adresse auf abort(); schieben und dann mit ach und krach das Progrämmchen killen.

    Ich habe tatsächlich gerade zuerst ​gosub geschrieben... naja, gut dass ich noch nie auf einer echten C64/128 programmiert habe :D

    Wie mein C/++-iger Ansatz nun in .net aussehen würde, weiß ich ehrlich gesagt nicht. In solchen Managed-Sprachen vermeide ich es so gut wie es geht, irgend einen Blödsinn mit ASM und Pointern zu machen.

    Ich belasse das hier aber als Mitleserkommentar. Das würde mich ja doch auch interessieren, was sich hier die Leute einfallen lassen.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)
    @DTF:
    Das ginge auch ohne GoTo

    VB.NET-Quellcode

    1. Sub Main()
    2. 'Initialisierung
    3. Do
    4. Try
    5. 'Hauptmenü etc.
    6. ThrowExceptionIfAppShallEnd()
    7. Catch Ex As ApplicationException
    8. Exit Do
    9. End Try
    10. Loop
    11. End Sub


    Die bisher über das Hauptmenü erstellten Klasseninstanzen implementieren ein Interface. Am Ende der Hauptmenüschleife wird die Abschlussmethode der erstellten Instanz aufgerufen, die dann eben etwas macht oder auch nicht. Bei der For-Schleifen-Variante feuern alle bis auf die Programmende-Klasse ein Event, damit das Hauptprogramm die Zählervariable auf Null setzt.
    Mit einem zuvor genutzten Do-Loop-Konstrukt war es

    VB.NET-Quellcode

    1. Do
    2. Loop Until ProgramShallEnd()
    Und ProgramShallEnd() war einfach nur von allen Klassen so implementiert, dass sie bis auf die Programmende-Klasse False zurückgegeben haben. Aber ich versuch mich ja eben in Bool-Fasten. Stattdessen könnten sie jetzt eben nix machen, nur die Programmende-Variante wirft eine Exception.
    Aber ja, dann könnte man Do und Try auch tauschen, dann spart man sich das Exit Do

    VB.NET-Quellcode

    1. Sub Main()
    2. 'Initialisierung
    3. Try
    4. Do
    5. 'Hauptmenü etc.
    6. ThrowExceptionIfAppShallEnd()
    7. Loop
    8. Catch Ex As ApplicationException
    9. End Try
    10. End Sub


    @siycah: Mir fällt zwar notfalls noch das Rabiat-End ein, aber dann sollte ich mich vorher noch um die Aufräumarbeiten kümmern …
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „VaporiZed“ ()

    siycah schrieb:

    Da würde ich mir stumpf von allen Funktionen die Adressen holen und einfach solange mit setjmp/longjmp hin- und herspringen.


    Das können wir einfacher haben, wird zwar wie ein bool interpretiert, aber ist ja keiner. Aber mit VB oder C#, da fällt mir echt nur Try/Catch ein.

    VB.NET-Quellcode

    1. #include <iostream>
    2. using namespace std;
    3. int main()
    4. {
    5. int endless = 1;
    6. while (endless)
    7. {
    8. cout << "Enter 0 to exit" << endl;
    9. endless = cin.get() - 48;
    10. }
    11. }


    Edit: Wobei while ja doch als Bedingung gewertet werden könnte. ;(
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    DTF schrieb:

    Edit: Wobei while ja doch als Bedingung gewertet werden könnte.


    Mein Reden :D

    Anstatt einer ​while kann man aber auch immer:

    C-Quellcode

    1. for (;;) {
    2. }


    nehmen :)

    VaporiZed schrieb:

    Do
    Loop Until ProgramShallEnd()


    Aber damit hast du wieder eine boolsche Überprüfung drin. Das ist ja auch nur eine fußgesteuerte bedingte Schleife.

    VaporiZed schrieb:

    @siycah: Mir fällt zwar notfalls noch das Rabiat-End ein, aber dann sollte ich mich vorher noch um die Aufräumarbeiten kümmern …


    Die Aufräumarbeiten sind ja erstmal nebensächlich. Alle Resourcen die dein Programm allokiert wird das Framework dann schon zerstören; das ist mittlerweile auch bei nativen Sprachen und modernen Betriebssystemem der Fall. Außer du meinst natürlich Daten die du noch im RAM hast. In dem Fall definitv raus damit :D
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)
    Normalerweise endet das Programm nach der Schleife. Also setzt du den counter immer auf 0 damit die Schleife weiterläuft, oder verstehe ich das nicht richtig?
    Und wenn man das so sieht dann muss in einer For schleife an sich auch irgendwo geprüft werden, ob der Counter weiterhin < 1 ist. Sonst wäre eine For 1 To 1 dasselbe wie ganz ohne Schleife.

    Wenn ich eine Konsolenanwendung habe, die nicht ohne Userinput aufhört, dann habe ich eine While Schleife, die weiterhin Eingaben kassiert. Aber die While braucht ja schon nen Bool
    Interessehalber welchen Gewinn hätte ich ohne Bool?


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    siycah schrieb:

    Aber damit hast du wieder eine boolsche Überprüfung drin. Das ist ja auch nur eine fußgesteuerte bedingte Schleife.
    Richtig. Ich hab wohl nicht ausreichend formuliert, dass das eine vergangene Variante war. Danach bin ich zur For-Schleife und dann zur Exception-Variante übergegangen, die mit einem eigenen Exception-Typ läuft, um da nix zu fangen/catchen, was nicht vorgesehen ist. Mir ist bewusst, dass dieser Art von Try-Catch-Missbrauch auch nur eine andere Form von GoTo ist, aber hätte ich eine bessere Lösung, hätte ich den Thread nicht aufgemacht :)

    @Haudruferzappeltnoch: Ja, das Verwenden der For-Schleife ist im Grunde genommen auch eine Bedingungsgeschichte, daher auch nicht der Weisheit letzter Schluss. Ob Do-Loop Until/While, While-End While oder For - alles arbeitet mit Bedingungen.


    Warum mach ich das: If und Nothing schwirren in meinen Programmen massenhaft rum. Ich lese seit einiger Zeit Bücher und Webeinträge, wie man den eigenen Code besser machen kann und es hat sich für mich rauskristallisiert, dass beides mich in der verwendeten Menge von einer besseren OOP abhält. In meinem kleinen Testprogramm habe ich gefühlt viel intensiver mit OOP zu tun als bisher. Daher mein Experiment.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Also das heißt für mich das Programm muss einen Weg gehen, ohne jemals eine Kreuzung zu sehen. Also so würde es wirklich ohne erstmal laufen, aber Abschalten ist dann nicht mehr ohne links rechts wählen.

    VB.NET-Quellcode

    1. Sub Main()
    2. Console.WriteLine("Ich gehe nie wieder aus. Muhahahaha")
    3. su1()
    4. End Sub
    5. Private Sub su1()
    6. Dim a = Console.ReadLine()
    7. Dim x = Integer.Parse(a)
    8. su2()
    9. End Sub
    10. Private Sub su2()
    11. Dim a = Console.ReadLine()
    12. Dim x = Integer.Parse(a)
    13. su1()
    14. End Sub

    Man kann irgendwas einstreuen das bei bestimmten Input eine Exception wirft. Die darf man aber auch nicht Abfangen weil Catch wäre wieder abgebogen.
    Ich gehe auch mal davon aus, dass Parse prüfen wird, ob a aus Ziffern besteht.

    Und dann hat die Konsole ja noch den X-Button, wie macht man den aus?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Abbiegen mit If ist mein Problem.

    Wenn es danach geht, ohne Catch auszukommen, könnte man auch mit

    VB.NET-Quellcode

    1. Try
    2. Do
    3. '… irgendwann eine Exception werfen
    4. Loop
    5. Finally
    6. End Try
    arbeiten. Aber das würde den Programmabbruchs-ExceptionTyp beseitigen und bei allen unerwarteten Exceptions das Programm "regulär" beenden.

    Der [X]-Button ist vermutlich nix anderes als End. Die Radikalabschaltmethode ohne Aufräumen :/
    Klar, ich könnte ne bedingungslose Do-Loop verwenden und bei Programmendewunsch aufräumen und End aufrufen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Hm, ein leeres Catch könnte man als nicht abgebogen werten.
    Ich sehe nicht den Unterschied, ob ich If hinschreibe oder durch andere Wörter das verschleiere. Entweder der Prozessor muss was prüfen oder nicht.

    Der User kann 20 mal was machen danach schaltet das Programm ab, das ist der einzige Weg wie der Prozessor einfach geradeaus laufen kann.
    Je mehr ich drüber nachdenke, desto mehr finde ich es geht nicht unbedingt. Allein dadurch das eine Entscheidung getroffen wird, ist das ja schon bedingt, also abhängig von dieser Entscheidung. Auch beim Try/Catch, entweder kann man weiter machen oder nicht, mit der Bedingung ob's funktioniert oder eine Exception geworfen wird.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Ein Beispiel, wie ich mit der Eingabe des Benutzers ohne Bedingung eine Auswahl treffen kann:
    Ich lege ein Feld an: {ungültig, Auswahl1, Auswahl2, Programmende, ungültig}
    Dann wandel ich die Benutzereingabe in einen Integerwert um und begrenze die Werte auf 0 bis 4. Dadurch werden ungültige Eingaben und Negativwerte zu 0, Eingaben größer 4 werden zu 4. Und die sich daraus ergebende Zahl nehm ich als Feldindex her, um das gewählte Feldelement zu bekommen. Danach rufe ich für das gewählte Feld-Element meine Methoden auf: Ausführen, Rückmeldung geben, Programm beenden.
    Bei ungültig passiert beim Ausführen nix, Text ist dann "ungültige Eingabe", bei Programm beenden passiert nix.
    Bei Auswahl1 und Auswahl2 wird eben was gemacht, Text ist dann "erledigt", bei Programm beenden passiert nix.
    Bei Programmende wird nix gemacht, Text ist leer, bei Programm beenden wird derzeit eine ProgrammEndeException geworfen, um die Hauptschleife zu unterbrechen.

    So kann ich einige Bedingungen beseitigen, also auf If und Booleans verzichten und trotzdem dem Benutzer verschiedene Aktionen ermöglichen.
    Die Bedingung/Entscheidung setzt der User, nicht der Code.
    Bei WinForms wäre es m.E. einfacher: Zwei Buttons ergeben zwei EventHandler - auch hier entscheidet der User, nicht der Code. Das Programmende geht auch einfach: Event-Feuern ans HauptForm und dort Close.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Woher weißt du z.B. das ein Input > 4 ist? Das ist schon eine Verzweigung

    Du könntest für jede denkbare Eingabe eine eigene Methode bauen und verschiebst damit die Verzweigung bis runter auf den User selbst. Aber ich denke Sinn jeder Anwendung ist genau solche Userverzweigungen zu verallgemeinern und in kleinerem Umfang abzuarbeiten mit dann selbsterzeugten Verzweigungen der Verallgemeinerungen.
    Indem ich zuerst die Eingabe zu einem Integer parse und dann mit Math.Min und Math.Max die sich ergebende Zahl immer auf Werte zwischen 0 und 4 begrenze. So wird aus der Benutzereingabe entweder eine gültige Auswahl von 1-3 oder endet eben bei 0 oder 4, welche als ungültige Eingabe gewertet werden. Ich selbst habe kein If im Code und die Umwandlung der Benutzereingabe zu einem Feldindex ist sehr kurz.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Also wählst du ein Array Element aus, um in eine Methode zu springen, ich schätze das geht mit Tasks oder Delegaten, da kenn ich mich leider nicht gut mit aus.
    Und bei der Hauptschleife hatte ich vermutet, dass die nur läuft weil du den counter immer zurücksetzt. Wenn Programmende das nicht macht dann hört es doch ohne Exception auf.
    So etwas wie „Bedingungslose Konsolenapp” gibt es nicht, aber eine „Bedingungslose Kapitulation” z.B. schon – ein Blick ins Lexikon hilft manchmal ganz gut, um die Dinge richtig einordnen zu können, Lexika und Fachbücher wären bestimmt noch besser. „Eine Konsolenapp ohne IF-Anweisungen im Code” müsste man das Ding eigentlich nennen, damit man überhaupt weiß, worum es geht, wenn man so eine merkwürdige Zeile liest, wobei die IF-Anweisung an sich nur ein Konstrukt auf einer höheren Abtraktionsebene ist, extra für den Menschen erschaffen, damit sich der Programmablauf besser lesen lässt – auf Prozessorebene gibt es das so gar nicht, dort wird alles mit Flags (entsprechend gekippten Bits) entschieden und abgearbeitet – und diese Unterscheidung passiert quasi ständig oder laufend. Egal, ob die CPU eine Abzweigung (bedingten Sprung) macht, eine Schleife durchläuft, Do-Loop-While-Until passiert, eine Addition, Subtraktion oder Multiplikation vollführt, es läuft alles mit diesen internen Flags, insofern ist das mit diesem „Code ohne IFs” eher eine Art Selbstbetrug oder Spielerei, die die Wirklichkeit nicht widerspiegelt und vermutlich auf Unwissen basiert oder die Verwechslung einfach nur mit der ersten Abstraktionsebene, die in der Regel mit der Sprache C beginnt, zusammenhängt und dort ihre Quelle hat. Es gibt normalerweise auch keine Assemblerbefehle, die IF heißen und wo man dann einen komplexen Ausdruck zum Abfragen dahinterschreiben kann, aber durchaus Hilfen in den IDEs wie Macros, wo man im Assemblercode eine komplexe IF-Anweisung und noch vieles mehr verwenden kann, damit der Mensch das besser lesen bzw. einfacher schreiben kann – am Ende macht der Compiler daraus eh nur Assemblerbefehle, wo nur Flags unterschieden werden; aus Mnemonics werden dann am Ende einfach nur Zahlen in Binärform vorliegen. Moderne Prozessoren haben mittlerweile explizit sogenannte bedingte Befehle, wo dann diese Flags unmittelbar zu differenziertem Ausführen eines solchen Befehls im Hintergrund führen und zum Einsatz kommen, ohne dass man noch andere Befehle mit Flag-Unterscheidung dafür benutzen muss; auch Befehle mit drei Operanden sind möglich.
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.
    @Haudruferzappeltnoch: Nee, ist viel einfacher. Nix mit Tasks und Delegates.
    Es gibt ein Interface mit den genannten Aktionen, und das Feld, aus dem der User was auswählt, besteht aus Klasseninstanzen, welche das Interface implementieren:
    hier mal Pseudocode:

    VB.NET-Quellcode

    1. Friend MyInterface
    2. Sub SendMenuText()
    3. Sub Execute()
    4. Sub SendTextAfterExecution()
    5. Sub SendAppEndMessage()
    6. End Interface
    7. '…
    8. Private GewählteSubroutine As MyInterface
    9. '…
    10. Private Sub AuswahlDerSubroutine()
    11. Dim MöglicheSubroutinen = {New InvalidChoice, New SubRoutine1, New SubRoutine2, New CloseAppRoutine, New InvalidChoice}
    12. GewählteSubroutine = MöglicheSubroutinen(GeparsteBenutzereingabe_EineZahlZwischen0und4)
    13. End Sub

    All diese Klassen implementieren das Interface, sodass man dann einfach später aufrufen kann:

    VB.NET-Quellcode

    1. GewählteSubroutine.SendMenuText()
    2. GewählteSubroutine.Execute()
    3. GewählteSubroutine.SendTextAfterExecution()
    4. GewählteSubroutine.SendAppEndMessage()
    ohne sich darüber Gedanken machen zu müssen, welche Auswahl getroffen wurde, weil alle Klassen etwas machen, was bei jeder Methode sinnvoll ist.
    InvalidChoice macht bei SendMenuText nix, auch nicht bei Execute, bei SendTextAfterExecution schickt es eben "ungültige Eingabe" an das Hauptmodul und auch bei SendAppEndMessage passiert nix.
    Die beiden Aktionsklassen machen eben was bei Execute, und die CloseAppRoutine-Klasse macht was besonderes bei SendAppEndMessage.
    Ganz ohne If oder Boolean. Was ja mein eigentliches Ziel bei diesem kleinen Projekt ist.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Haudruferzappeltnoch schrieb:

    Also wählst du ein Array Element aus, um in eine Methode zu springen, ich schätze das geht mit (...) Delegaten

    Damit – also z.B. einem Array aus Delegaten – könnte man sehr viel oder vielleicht sogar fast alles lösen – wem der Delegat zu exotisch oder zu kompliziert ist, der könnte auch spaßhalber auf die alte, mittlerweile verhasste und verpönte CallByName-Methode zurückgreifen und dann die Sprünge mit einer Stringvariable kreieren. Egal, ob mit einem Delegaten oder einem Relikt aus ferner Zeit, so etwas wie If Eingabe >= 100 And Eingabe < 1000 Then und ähnliche Ausdrücke könnte man damit auf jeden Fall realisieren oder erfolgreich abfangen – natürlich nicht, indem man ein Array aus 1000 Delegaten und 1000 Unterprogrammen schreibt, sondern man bearbeitet erstmal mathematisch ein wenig die Eingabe, um die Anzahl der Möglichkeiten drastisch zu reduzieren. Wenn die Eingabe ein Integer wäre, könnte man erstmal eine IntegerDivision mit 1000 durchführen (Eingabe\1000), um zu schauen, ob die Zahl unter 1000 liegt, d.h. das Ergebnis dieser IntegerDivision als ArrayIndex nehmen; wenn JA, würde man bei Index 0 einspringen und gleichzeitig wissen, dass die Zahl unter 1000 liegt; im zweiten Schritt dann mit der ursprünglichen Zahl eine IntegerDivision mit 100 durchführen, um zu schauen, ob die Zahl unter 100 liegt (ArrayIndex als Integer wäre dann 0). Wenn sie nicht unter 100 liegt, also ein Catch bei Try und kein Einsprung bei ArrayIndex 0 passiert ist, dann wird sie wohl irgendwo in dem gesuchten IF-Bereich liegen. Dafür bräuchte man nur jeweils einen, also insgesamt zwei Delegaten (oder CallByNames) und zwei Subroutinen, einen fehlerhaften Verweis könnte oder müsste man mit Try-Catch abfangen. Möglicherweise bräuchte man noch ein bis zwei zusätzliche indexierte Subroutinen als Zwischenstationen. Eventuelle (Rück)sprungadressen oder so etwas in der Art könnte man auch als Argumente an die Subroutinen übergeben, wäre aber nicht zwingend notwendig, wenn man solche Aktionen immer wieder neu im Code schreibt, wo dann die Adressen eindeutig klar sind, oder weiß, wie man sie wiederverwenden/recyceln könnte. Informationen könnte man grundsätzlich ganauso austauschen oder übermitteln. Negative Eingabe könnte man mit UInteger oder gleich bei der Eingabe durch casten, umformen, Betrag nehmen, quadrieren & wurzelziehen, Wiederholung der Eingabe, Offset einbauen etc. unterbinden oder abfangen. Man wüsste sogar auch, ob die Eingabe bei größer/gleich 1000 oder unter 100 lag, also hätte quasi auch das Else des IFs parat. Ziemlich viel Aufwand für nur eine IF-Zeile, aber – wie ich am Anfang des Paragraphen schon erwähnt habe – möglich wäre bestimmt fast alles. Ersatz für Abfragen wie If Eingabe = 1, 2, 3, 4, 5 oder = "a", "b", "c", "d", "e" zu schaffen wäre vermutlich etwas einfacher zu realisieren in diesem Kontext.
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.

    Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von „Gregor Jasinski“ ()

    Kannst du dann nicht die Dinge, die aufgeräumt werden müssen an die EndeRoutine ByRef übergeben, dort aufräumen und dann End aufrufen?
    MinMaxParse und Schleife sind aber noch gemogelt.^^
    Zwei Methoden die sich endlos gegenseitig aufrufen können das gleiche wie die Schleife nur ohne Prüfung. Aber ich denke mal damit belastet man irgendwie seine Ressourcen.

    Hab noch was besseres:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Module Module1
    2. Private aufräumen As Object
    3. Private GewählteSubroutine As Interface1
    4. Sub Main()
    5. Console.WriteLine("Wähle")
    6. AuswahlDerSubroutine()
    7. End Sub
    8. Friend Sub AuswahlDerSubroutine()
    9. Dim a = Console.ReadLine()
    10. Dim MöglicheSubroutinen As Interface1() = {New Class3, New Class4, New ClassEnde}
    11. GewählteSubroutine = MöglicheSubroutinen(Math.Max(Math.Min(Integer.Parse(a), 2), 0))
    12. GewählteSubroutine.Tu3()
    13. GewählteSubroutine.Tu4()
    14. GewählteSubroutine.Ende()
    15. End Sub
    16. Friend Sub AufräumenUndTschüss()
    17. End Sub
    18. End Module
    19. Public Class ClassEnde
    20. Implements Interface1
    21. Private Sub Tu3() Implements Interface1.Tu3
    22. End Sub
    23. Private Sub Tu4() Implements Interface1.Tu4
    24. End Sub
    25. Private Sub Ende() Implements Interface1.Ende
    26. AufräumenUndTschüss()
    27. End Sub
    28. End Class
    29. Public Class Class3
    30. Implements Interface1
    31. Private Sub Tu3() Implements Interface1.Tu3
    32. Console.WriteLine("3 abgearbeitet")
    33. End Sub
    34. Private Sub Tu4() Implements Interface1.Tu4
    35. End Sub
    36. Private Sub Ende() Implements Interface1.Ende
    37. AuswahlDerSubroutine()
    38. End Sub
    39. End Class
    40. Public Class Class4
    41. Implements Interface1
    42. Private Sub Tu3() Implements Interface1.Tu3
    43. End Sub
    44. Private Sub Tu4() Implements Interface1.Tu4
    45. Console.WriteLine("4 abgearbeitet")
    46. End Sub
    47. Private Sub Ende() Implements Interface1.Ende
    48. AuswahlDerSubroutine()
    49. End Sub
    50. End Class


    Da wird nichtmal mehr was übergeben. Und auch nicht End aufgerufen. Die Konsole schließt durch Ende der Sub Main

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()