[C#] Gebruik van goto uit den boze?

Pagina: 1
Acties:
  • 464 views sinds 30-01-2008
  • Reageer

  • Mastermind
  • Registratie: Februari 2000
  • Laatst online: 29-11 15:35
Zoals men wel weet bevat C# het impopulaire keyword goto. Maar is het echt zo slecht dit te gebruiken, als het in een oogopslag is te zien waar hij heenspringt?

Neem de volgend stukje uit mijn code:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TreeNode selectedTreeNode = null;
for (int i = 0; i < treeTableGepland.TreeModel.GetChildCount(null); i++)
{
    TreeNode node = (TreeNode)treeTableGepland.TreeModel.GetChild(null, i);
    foreach (TreeNode node2 in node.Nodes)
    {
        if (node2.Tag as CustomActivity == activity)
        {
            selectedTreeNode = node2;
            goto NodeFound; // Impopulaire goto
        }
    }
}
NodeFound:
if (selectedTreeNode != null)
{
    treeTableGepland.ExpandRow(selectedTreeNode.Parent);
// etc.


Is het werkelijk zo ranzig uit de foreach te jumpen, terwijl het duidelijk is waar hij heenspringt? Of is het netter een boolean te zetten, en in de parent loop deze boolean met een if te bekijken om dan te breaken?

Laten we het geval van een Abort/Retry/Ignore dialogbox bekijken:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void btnSave_Click(object sender, EventArgs e)
{
    Try:
try
{
    if (!u.Text.Equals(String.Empty))
    {
        int partijNr = Convert.ToInt32(u.Text);
        int ID = GetIDFromName(u.Name);
// ... try to save
    }
}
catch (Exception ex)
{
    DialogResult result = MessageBox.Show("Fout bij bewaren van partij " + u.Text + "\n\n " + ex, "Foutmelding", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error);
    if (result == DialogResult.Retry) goto Try; // Ranzige goto
    else if (result == DialogResult.Abort) ExitDialog();
}
// more code..
}


Hier is het ook duidelijk wat de goto doet. Ik kan me voorstellen als je over grote afstanden springt het lelijk en ongestructureerd is, maar als er zeer dichtbij gesprongen wordt, is het ook dan ranzig, als het een aantal if's en booleans scheelt?

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
TreeNode selectedTreeNode = null;

for (int i = 0; i < treeTableGepland.TreeModel.GetChildCount(null) && selectedTreeNode != null; i++)
{
    TreeNode node = (TreeNode)treeTableGepland.TreeModel.GetChild(null, i);
    foreach (TreeNode node2 in node.Nodes)
    {
        if (node2.Tag as CustomActivity == activity)
        {
            selectedTreeNode = node2;
            break;
        }
    }
}

if (selectedTreeNode != null)
{
    treeTableGepland.ExpandRow(selectedTreeNode.Parent);
// etc.


Klaar? Ben niet zeker of && de juiste notatie is in C#.

[ Voor 4% gewijzigd door Grijze Vos op 20-06-2007 15:25 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
Nu is het nog duidelijk te zien. Binnen een aantal maanden & code-wijzigingen later misschien niet meer.
Zowiezo is het niet moeilijk om dat naar iets te herschrijven, zonder dat goto nodig is, zoals Grijze Vos al laat zien.

https://fgheysels.github.io/


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Sommige talen (bijvoorbeeld Java en PHP) bieden wel de mogelijkheid om uit meerdere levels aan nesting tegelijk te springen. In PHP door een extra integer aan de break/continue mee te geven wat het aantal levels voorstelt, en in Java (wat mooier imho) een labelnaam die je aan de betreffende nesting gekoppeld hebt.

Als dat niet kan, en er erg diep genest is (soms is dat slecht design, soms is het nou eenmaal niet anders) kán een goto prettiger zijn dan het bijhouden van allerlei booleans. Maar in jouw voorbeeld zou ik voor de oplossing van Grijze Vos gaan.

Een ding waar goto's natuurlijk terdege handig voor zijn is code generatie van compilers die naar een bepaalde taal compileren :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Armageddon_2k
  • Registratie: September 2002
  • Laatst online: 01-12 12:22

Armageddon_2k

Trotse eigenaar: Yamaha R6

Jeuj, spagetti code :Y)

Maar het goto gebruiken, is netzo iets als je doodvonnis tekenen..

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
.oisyn schreef op woensdag 20 juni 2007 @ 15:32:
Een ding waar goto's natuurlijk terdege handig voor zijn is code generatie van compilers die naar een bepaalde taal compileren :)
Het kan zijn omdat ik vandaag te veel aan de red bull zit, maar kun je dit verduidelijken?

  • brama
  • Registratie: Februari 2001
  • Niet online
In java kun je for loops labels geven, en zo uit een specifieke (de buitenste) loop springen:

code:
1
2
3
4
5
6
7
8
foobar: for (int i = 0; i < obj.size(); i++) {
  for (int j = 0; j < obj.get(i).size(); j++) {
    //do something
    if (condition) {
      break foobar;
    }
  }
}


Dat doet in principe het zelfde. Kan dat in C# niet?

Zo niet, dan zou ik goto hier niet erg vinden, maar ik zou toch een boolean gebruiken omdat dat nou eenmaal de gangbare conventie is.

I mentioned it once, but I think I got away with it.


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
brama schreef op woensdag 20 juni 2007 @ 15:35:

Dat doet in principe het zelfde. Kan dat in C# niet?
Nope.
When multiple switch, while, do, for, or foreach statements are nested within each other, a break statement applies only to the innermost statement. To transfer control across multiple nesting levels, a goto statement (Section 8.9.3) must be used.
Tenzij het in 2.0 wel kan (docs van 1.1).

https://fgheysels.github.io/


  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Mastermind schreef op woensdag 20 juni 2007 @ 15:21:
Zoals men wel weet bevat C# het impopulaire keyword goto. Maar is het echt zo slecht dit te gebruiken, als het in een oogopslag is te zien waar hij heenspringt?
Jouw voorbeeld was een erg simpele, en ik moest al zoeken waar dat label ergens stond. Komt ook omdat ik goto's gewoon compleet ontwend ben natuurlijk, maar ik moest dus vooruit zoeken naar je goto, terwijl je prima d.m.v. een state (boolean) kan bepalen of je nog door moet zoeken. Ik ben ook nog nooit een situatie tegengekomen waar ik het hebben van een goto (ik was vergeten dat ze in C# nog bestonden) miste.

Ik vind in ieder geval een boolean minder geen reden een goto te gebruiken, al is het alleen maar omdat dankzei goto's de program flow vaak niet meer linear maakt waardoor de code lastiger te lezen wordt.

https://niels.nu


Verwijderd

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void btnSave_Click(object sender, EventArgs e)
{
DialogResult result = DialogResult.Retry;
do{
  try
  {
      if (!u.Text.Equals(String.Empty))
      {
          int partijNr = Convert.ToInt32(u.Text);
          int ID = GetIDFromName(u.Name);
  // ... try to save
      }
  }
  catch (Exception ex)
  {
      result = MessageBox.Show("Fout bij bewaren van partij " + u.Text + "\n\n " + ex, "Foutmelding", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error);
      if (result == DialogResult.Abort) {
        ExitDialog();
        break; // of "return" als ExitDialog() niet "more code..." behoort uit te voeren
      }
  }
} while (result == DialogResult.Retry);
  // more code..
}

[ Voor 11% gewijzigd door Verwijderd op 20-06-2007 15:58 . Reden: result was out of scope, foutje ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Glimi schreef op woensdag 20 juni 2007 @ 15:35:
[...]

Het kan zijn omdat ik vandaag te veel aan de red bull zit, maar kun je dit verduidelijken?
Een voorbeeld: Stel je ontwerpt een nieuwe programmeertaal. En stel dat die moet compilen naar native code. Dan moet je ook een assembler en een low-level optimizer gaan implementeren, en bovendien voor ieder platform een verschillende. Handiger is om de compiler van je programmeertaal C-code uit te laten voeren, die weer door een C compiler gehaald kan worden waarvan er honderden van bestaan voor vrijwel elk mogelijk platform. In dat soort situaties kan het genereren van een goto statement veel handiger zijn dan jezelf in rare bochten moeten wringen om op een gestructureerde manier van de ene plek naar de andere te springen (natuurlijk niet omdat de gebruiker van jouw taal ook goto gebruikt, maar omdat een bepaalde taalconstructie (exceptions bijvoorbeeld) dat nodig heeft) - de uiteindelijke C code is toch niet bedoeld om door een mens gelezen te worden, dus het argument dat goto dan lelijk is gaat niet op.

Voor .Net en in het specifiek C# gaat dit wellicht wat minder op want volgens mij is het net zo handig om .Net IL te genereren als C# code, desalniettemin, als je je niet wilt verdiepen in IL en je C# al kent, en je bent een .Net scripttaal aan het maken oid, dan kan het handig zijn :).

[ Voor 5% gewijzigd door .oisyn op 20-06-2007 16:05 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
.oisyn schreef op woensdag 20 juni 2007 @ 16:04:
[...een C backend voor je compiler ...]
Ja sorry, was toch de red bull :+ Er zijn trouwens nog wel iets talen die echt bedoeld zijn als backend-talen C-- waar Simon P Jones ook aan meegewerkt heeft en LLVM. Ze bevielen me erg goed voor code generatie mede door de SSA property en de grote hoeveelheid optimalisaties welke ze uitvoeren, waardoor je toch nog een beetje naief kan blijven in je compiler :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Glimi schreef op woensdag 20 juni 2007 @ 16:31:
[...]
Ja sorry, was toch de red bull :+
Ik vond het al apart dat ik het jou moest gaan uitleggen :P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • sig69
  • Registratie: Mei 2002
  • Laatst online: 01:51
whoami schreef op woensdag 20 juni 2007 @ 15:29:
...zoals Grijze Vos al laat zien.
Alleen jammer dat zijn voorbeeld niet klopt...

Edit: niet toegevoegd... 8)7

[ Voor 10% gewijzigd door sig69 op 20-06-2007 17:19 ]

Roomba E5 te koop


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Euh ja, dat is toch precies wat whoami zegt? :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Mastermind schreef op woensdag 20 juni 2007 @ 15:21:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public TreeNode FindNodeWhere....()
{
    for (int i = 0; i < treeTableGepland.TreeModel.GetChildCount(null); i++)
    {
        TreeNode node = (TreeNode)treeTableGepland.TreeModel.GetChild(null, i);
        foreach (TreeNode node2 in node.Nodes)
        {
            if (node2.Tag as CustomActivity == activity)
            {
                return node2;
            }
        }
    }
    return null;
}

TreeNode selectedTreeNode = FindNode();

if (selectedTreeNode != null)
{
    treeTableGepland.ExpandRow(selectedTreeNode.Parent);
// etc.
Ik zou het denk zo oplossen. Als je diepe nesting hebt is het meestal gewoon goed mogenlijk om dit in duidelijk methodes op te delen. Omdat elke functie dan een duidelijk doel heeft is veel sneller te zien wat er gebeurt. Het is dan wel belangrijk om duidelijke methode namen te bedenken.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Maar dan begeef je je wel op glad ijs, want dan kom je op de discussie waar iets minder mensen het met elkaar eens zijn dan bij de goto (die vrijwel iedereen wel evil vindt): mag een functie meerdere return-statements hebben :P

[ Voor 9% gewijzigd door .oisyn op 20-06-2007 17:04 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • EXX
  • Registratie: Juni 2001
  • Laatst online: 01-12 12:06

EXX

EXtended eXchange

Multiple returns vind ik zelf ook al zoiets discutabels. Het is natuurlijk handig, maar IMHO heeft een function 1 entry en 1 exit point.

Bij de bovenstaande, korte functie is het niet zo een probleem, maar als de functions wat uitgebreider worden en er meerdere returns hebben wordt het voor de maintenance programmer al snel moeilijk te onderhouden.

edit:
spuit 11

For it is the doom of men that they forget...           Huidige en vroegere hardware specs         The Z80 is still alive!


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Ik vind doorgaans een paar exit points in een functie leesbaarder dan een paar breaks of nog erger, goto's.

Zodra je meerdere levels moet gaan breken uit je loops kan het vaak toch wel op een andere/betere manier.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

sig69 schreef op woensdag 20 juni 2007 @ 16:52:
[...]

Alleen jammer dat zijn voorbeeld niet klopt...

Edit: niet toegevoegd... 8)7
Wat klopt er dan niet aan? :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 17:20

Janoz

Moderator Devschuur®

!litemod

Heeft het tweede stuk code trouwens niet een memory leak omdat de stack steeds groter wordt? Binnen de catch scope wordt immers weer een nieuwe try gestart bij het terug springen. Het moet wel een behoorlijk slimme compiler of runtime zijn die het verwerken van die scope veranderingen allemaal aankan.

Dat tweede stukje zou ik gewoon herschrijven naar een 'repeat { ... } until success'.

[ Voor 12% gewijzigd door Janoz op 20-06-2007 17:33 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik neem aan dat die goto binnen de catch wel betekent dat het catch blok afgesloten wordt. Net zoals in C++ ook gewoon alle scoped objecten worden gedestruct als je met goto uit een scope springt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Serpie
  • Registratie: Maart 2005
  • Laatst online: 01-07-2023
EXX schreef op woensdag 20 juni 2007 @ 17:05:
Multiple returns vind ik zelf ook al zoiets discutabels. Het is natuurlijk handig, maar IMHO heeft een function 1 entry en 1 exit point.

Bij de bovenstaande, korte functie is het niet zo een probleem, maar als de functions wat uitgebreider worden en er meerdere returns hebben wordt het voor de maintenance programmer al snel moeilijk te onderhouden.

edit:
spuit 11
[miereneukmode]
Tja voor returns zou het nog discutabel kunnen zijn, feitelijk is het throwen van een exception ook al een exit point, dus 1 exit point gaat al niet (altijd) meer op (Wiki)
[/miereneukmode]

Voor korte functies vind ik het inderdaad wel mooi om de return bovenin te zetten:
C#:
1
2
3
4
5
if (parameter == null) {
  return false;
}
//Do something else
return true;

  • xx77qq
  • Registratie: Januari 2004
  • Niet online
Mastermind schreef op woensdag 20 juni 2007 @ 15:21:
Zoals men wel weet bevat C# het impopulaire keyword goto. Maar is het echt zo slecht dit te gebruiken, als het in een oogopslag is te zien waar hij heenspringt?
Lijkt me niet, duidelijkheid van code is een heel belangrijk aspect. Helaas is er een hele generatie gebrainwashed dat goto's slecht zijn.
Neem de volgend stukje uit mijn code:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TreeNode selectedTreeNode = null;
for (int i = 0; i < treeTableGepland.TreeModel.GetChildCount(null); i++)
{
    TreeNode node = (TreeNode)treeTableGepland.TreeModel.GetChild(null, i);
    foreach (TreeNode node2 in node.Nodes)
    {
        if (node2.Tag as CustomActivity == activity)
        {
            selectedTreeNode = node2;
            goto NodeFound; // Impopulaire goto
        }
    }
}
NodeFound:
if (selectedTreeNode != null)
{
    treeTableGepland.ExpandRow(selectedTreeNode.Parent);
// etc.


Is het werkelijk zo ranzig uit de foreach te jumpen, terwijl het duidelijk is waar hij heenspringt? Of is het netter een boolean te zetten, en in de parent loop deze boolean met een if te bekijken om dan te breaken?
Zeker niet, vooral als je nog meerder van dit soort vergelijkingen sequentieel gaat uitvoeren. Het uitsparen van een boolean en het voorkomen van het vervuilen van je if constructies rechtvaardigen het gebruik van goto (performance technisch is het ook nog een sneller, maar dat is premature optimization.). "Less is more" geldt ook hier.
Vaak kan je met exception handling hetzelfde bereiken.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
xx77qq schreef op woensdag 20 juni 2007 @ 19:39:
Lijkt me niet, duidelijkheid van code is een heel belangrijk aspect. Helaas is er een hele generatie gebrainwashed dat goto's slecht zijn.
Je weet dat deze 2 beweringen elkaar tegenspreken he? Waarom denk je dat goto's als evil worden gezien, omdat ze de code duidelijker maken?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
xx77qq schreef op woensdag 20 juni 2007 @ 19:39:
[...]


Lijkt me niet, duidelijkheid van code is een heel belangrijk aspect. Helaas is er een hele generatie gebrainwashed dat goto's slecht zijn.

[...]

Zeker niet, vooral als je nog meerder van dit soort vergelijkingen sequentieel gaat uitvoeren. Het uitsparen van een boolean en het voorkomen van het vervuilen van je if constructies rechtvaardigen het gebruik van goto (performance technisch is het ook nog een sneller, maar dat is premature optimization.). "Less is more" geldt ook hier.
Vaak kan je met exception handling hetzelfde bereiken.
Ik laat maar even alletwee je quotes staan, want als je nog meerder van dit soort vergelijkingen sequentieel gaat uitvoeren binnen deze functie dan valt het buiten je scherm en dan ben opeens wel het overzicht kwijt. Dus oftewel als er iemand over 2 maanden besluit er nog even 50 regels code tussen te proppen dan ben je het overzicht kwijt.

Het uitsparen van een boolean in zo'n simpel stukje code vind ik nou niet echt reden om een goto te gebruiken, er zijn wel redenen voor, maar dit voorbeeld is er imho geen van.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

xx77qq schreef op woensdag 20 juni 2007 @ 19:39:

Lijkt me niet, duidelijkheid van code is een heel belangrijk aspect. Helaas is er een hele generatie gebrainwashed dat goto's slecht zijn.
En gelukkig maar. Misschien ben je niet helemaal bekend met de definitie van "evil" danwel "slecht" in de ICT? Als iets evil is betekent dat niet dat je het nooit moet gebruiken. Het betekent dat je het niet zonder meer moet gebruiken, en als je het doet dat je dat weloverwogen doet en het het beste alternatief is voor het probleem dat je op wilt lossen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • xx77qq
  • Registratie: Januari 2004
  • Niet online
farlane schreef op woensdag 20 juni 2007 @ 20:48:
[...]


Je weet dat deze 2 beweringen elkaar tegenspreken he? Waarom denk je dat goto's als evil worden gezien, omdat ze de code duidelijker maken?
Goto's worden als evil gezien vanwege Edsger dijkstra's 'Go To statement considered harmful' uit 1968. De tijden zijn veranderd, de programmeertalen zijn verder gegroeid. Als je met een goto statement het nesten van if constructies kan voorkomen dan is dat een voordeel.

Wat is er mis met een 'goto failed' of 'goto done', spreekt toch helemaal voor zich?

  • xx77qq
  • Registratie: Januari 2004
  • Niet online
Gomez12 schreef op woensdag 20 juni 2007 @ 21:11:
[...]

Ik laat maar even alletwee je quotes staan, want als je nog meerder van dit soort vergelijkingen sequentieel gaat uitvoeren binnen deze functie dan valt het buiten je scherm en dan ben opeens wel het overzicht kwijt. Dus oftewel als er iemand over 2 maanden besluit er nog even 50 regels code tussen te proppen dan ben je het overzicht kwijt.
Even er 50 regels tussen proppen? Tijd om te refactoren, je functie lijkt me dan wel erg veel regels te gaan bevatten.
Het is onleesbaarder als je een break; plaatst die pas 50 regels verder uit de lus springt.
Het uitsparen van een boolean in zo'n simpel stukje code vind ik nou niet echt reden om een goto te gebruiken, er zijn wel redenen voor, maar dit voorbeeld is er imho geen van.
Het is meestal geen common practice, maar er is eigenlijk niks mis mee. Als goto verkeerd zou zijn dan was het geen keyword in de taal.

  • Not Pingu
  • Registratie: November 2001
  • Laatst online: 20-11 21:40

Not Pingu

Dumbass ex machina

xx77qq schreef op woensdag 20 juni 2007 @ 21:44:
[...]


Goto's worden als evil gezien vanwege Edsger dijkstra's 'Go To statement considered harmful' uit 1968. De tijden zijn veranderd, de programmeertalen zijn verder gegroeid. Als je met een goto statement het nesten van if constructies kan voorkomen dan is dat een voordeel.

Wat is er mis met een 'goto failed' of 'goto done', spreekt toch helemaal voor zich?
Echter zijn er sinds 1968 juist meer flexibele control statements beschikbaar, dus er zou juist nog minder reden moeten zijn om goto te gebruiken.
Dijkstra's voornaamste wrok tegen goto was dat zelfs een programmeur met de beste bedoeling er nog een warboel van kan maken. Door goto niet te gebruiken word je gedwongen je code beter te structureren.

Certified smart block developer op de agile darkchain stack. PM voor info.


  • xx77qq
  • Registratie: Januari 2004
  • Niet online
.oisyn schreef op woensdag 20 juni 2007 @ 21:19:
[...]

En gelukkig maar. Misschien ben je niet helemaal bekend met de definitie van "evil" danwel "slecht" in de ICT? Als iets evil is betekent dat niet dat je het nooit moet gebruiken. Het betekent dat je het niet zonder meer moet gebruiken, en als je het doet dat je dat weloverwogen doet en het het beste alternatief is voor het probleem dat je op wilt lossen.
Als goto zo evil zou zijn waarom zit 'ie dan in de definitie van C# ?

Bij het woordje goto gaan een hoop mensen spatisch (no offense, niet persoonlijk bedoeld) reageren. Alsof er een vloek wordt uitgesproken.
Goto hoeft geen alternatief of een last resort te zijn, er is veel veranderd sinds 1968 ;-)

  • Not Pingu
  • Registratie: November 2001
  • Laatst online: 20-11 21:40

Not Pingu

Dumbass ex machina

xx77qq schreef op woensdag 20 juni 2007 @ 22:16:
Goto hoeft geen alternatief of een last resort te zijn, er is veel veranderd sinds 1968 ;-)
Is de werking van goto veranderd sinds 1968?

Certified smart block developer op de agile darkchain stack. PM voor info.


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
xx77qq schreef op woensdag 20 juni 2007 @ 21:44:
[...]


Goto's worden als evil gezien vanwege Edsger dijkstra's 'Go To statement considered harmful' uit 1968. De tijden zijn veranderd, de programmeertalen zijn verder gegroeid. Als je met een goto statement het nesten van if constructies kan voorkomen dan is dat een voordeel.
Juist, de talen zijn gegroeid, in een richting die het gebruik van goto onnodig maakt.
Wat is er mis met een 'goto failed' of 'goto done', spreekt toch helemaal voor zich?
Totdat er onderhoud gepleegd wordt en er 15 regels code tussen komen. Dan verlies je plotseling het overzicht.

Daarnaast is er natuurlijk nog het bewijzen van loop invarianten e.d., maar ik denk dat niemand die goto in zijn programmacode opneemt zich daar ooit mee bezig houdt.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • xx77qq
  • Registratie: Januari 2004
  • Niet online
Not Pingu schreef op woensdag 20 juni 2007 @ 22:20:
[...]


Is de werking van goto veranderd sinds 1968?
Nee. Echter, met destructors of het buiten de scope vallen van variabelen hoeft goto niet meer zo destructief te zijn bij verkeerd gebruik.
De evolutie van de talen heeft goto veiliger gemaakt.

Het probleem is dat 'goto's are evil' komt van die ene zin van Dijkstra, meestal niet in de juiste context gebruikt. Dijkstra had geen moeite met goto, hij wilde echter duidelijk maken dat het goto niet de manier is om alles aan elkaar te plakken.

  • xx77qq
  • Registratie: Januari 2004
  • Niet online
Grijze Vos schreef op woensdag 20 juni 2007 @ 22:28:
Daarnaast is er natuurlijk nog het bewijzen van loop invarianten e.d., maar ik denk dat niemand die goto in zijn programmacode opneemt zich daar ooit mee bezig houdt.
Mee eens. In dat soort situaties gebruik je geen goto.

  • Ontspannen
  • Registratie: Februari 2007
  • Laatst online: 11-10 10:33
Laats bij binair zoeken in een lijst nog een goto gebruikt.
Omdat de grenzen voor het midden veranderen en een recursieve oplossing minder efficient is. :+

  • Ontspannen
  • Registratie: Februari 2007
  • Laatst online: 11-10 10:33
Ontspannen schreef op woensdag 20 juni 2007 @ 23:13:
Laats bij binair zoeken in een lijst nog een goto gebruikt.
Omdat de grenzen voor het midden veranderen en een recursieve oplossing minder efficient is. :+
Grenzen voor het midden te bepalen. 8)7

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
xx77qq schreef op woensdag 20 juni 2007 @ 21:58:
[...]


Even er 50 regels tussen proppen? Tijd om te refactoren, je functie lijkt me dan wel erg veel regels te gaan bevatten.
Het is onleesbaarder als je een break; plaatst die pas 50 regels verder uit de lus springt.
50 regels was voorbeeld, maar de grap met refractoring en goto is dat als je niet goed oplet dat je juist door de spaghetti code van goto en refractoring dingen kan slopen ( denk aan 3 goto's naar dezelfde positie, maar vanwege refractoring werken er nog maar 2 goto's want de derde heb je opeens een verplichte variabele niet voor geset )

[...]


Het is meestal geen common practice, maar er is eigenlijk niks mis mee. Als goto verkeerd zou zijn dan was het geen keyword in de taal.
[/quote]
nonargument, geef mij een willekeurige hedendaagse programeertaal en ik kan minstens 10 keywords vinden die verkeerde common practice zijn. Soms zijn ze nodig / handig en daarvoor bestaat het keyword nog steeds, maar in 95% van de goto-gevallen is het onnodig en lelijk en onoverzichtelijk dus evil

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Ontspannen schreef op woensdag 20 juni 2007 @ 23:13:
Laats bij binair zoeken in een lijst nog een goto gebruikt.
Omdat de grenzen voor het midden veranderen en een recursieve oplossing minder efficient is. :+
Ho, een niet tail recursieve versie bedoel je :+

  • xx77qq
  • Registratie: Januari 2004
  • Niet online
Gomez12 schreef op woensdag 20 juni 2007 @ 23:32:
[...]

50 regels was voorbeeld, maar de grap met refractoring en goto is dat als je niet goed oplet dat je juist door de spaghetti code van goto en refractoring dingen kan slopen ( denk aan 3 goto's naar dezelfde positie, maar vanwege refractoring werken er nog maar 2 goto's want de derde heb je opeens een verplichte variabele niet voor geset )
In dat geval is goto een symptoon van slechte code geen oorzaak.

[...]
nonargument, geef mij een willekeurige hedendaagse programeertaal en ik kan minstens 10 keywords vinden die verkeerde common practice zijn. Soms zijn ze nodig / handig en daarvoor bestaat het keyword nog steeds, maar in 95% van de goto-gevallen is het onnodig en lelijk en onoverzichtelijk dus evil
Okay, geef eens 10 keywords van C# die verkeerde common practice zijn. En geef eens een aantal goto-gevallen die onnodig en lelijk zijn (code van vandaag de dag als het kan)?

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Mastermind schreef op woensdag 20 juni 2007 @ 15:21:
Laten we het geval van een Abort/Retry/Ignore dialogbox bekijken:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void btnSave_Click(object sender, EventArgs e)
{
    Try:
try
{
    if (!u.Text.Equals(String.Empty))
    {
        int partijNr = Convert.ToInt32(u.Text);
        int ID = GetIDFromName(u.Name);
// ... try to save
    }
}
catch (Exception ex)
{
    DialogResult result = MessageBox.Show("Fout bij bewaren van partij " + u.Text + "\n\n " + ex, "Foutmelding", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error);
    if (result == DialogResult.Retry) goto Try; // Ranzige goto
    else if (result == DialogResult.Abort) ExitDialog();
}
// more code..
}
Met anonieme methoden kan je abstraheren van deze "veel voorkomende" control-flow, wat je niet alleen de goto bespaart, maar om diverse andere redenen mooier is:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void btnSave_Click(object sender, EventArgs e)
{
    Repeater.Perform<Exception>
      ( delegate()
        {
            if (!u.Text.Equals(String.Empty))
            {
                int partijNr = Convert.ToInt32(u.Text);
                int ID = GetIDFromName(u.Name);
                // ... try to save
            }
        }
      , delegate(Exception ex)
        {
            DialogResult result = MessageBox.Show(...);
            if (result == DialogResult.Retry)
                return Repeater.Action.Repeat;
            else
            {
                ExitDialog();
                return Repeater.Action.Abort;
            }
        });

    // more code
}



Vervolgens moet je de control-flow waar je van geabstraheerd hebt nog wel ergens definieren, bijvoorbeeld iets als:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Repeater
{
    public enum { Repeat, Abort } Action;
    public delegate void TryDelegate();
    public delegate Action ErrDelegate<T extends Exception>(T ex);

    public static void Perform<T extends Exception>(TryDelegate tryBlock, ErrDelegate<T> errBlock)
    {
        while(true)
        {
            try
            {
                tryBlock();
            }
            catch(T ex)
            {
                Action result = errBlock(ex);
                if (result == Action.Abort)
                   break;
            }
        } 
    }
}


Ook je eerste voorbeeld kan je met anonieme functies zonder goto's schrijven:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public delegate void NodeVisitor(TreeNode selectedTreeNode);
public static void WithSelectedNode(NodeVisitor visitor)
{
    for (int i = 0; i < treeTableGepland.TreeModel.GetChildCount(null); i++)
    {
        TreeNode node = (TreeNode)treeTableGepland.TreeModel.GetChild(null, i);
        foreach (TreeNode node2 in node.Nodes)
            if (node2.Tag as CustomActivity == activity)
            {
                visitor(node2);
                return;
            }
    }
}


WithSelectedNode
  ( delegate(TreeNode selectedTreeNode)
    {
        treeTableGepland.ExpandRow(selectedTreeNode.Parent);
        // etc.
    } );


Programmeren met anonieme methoden is zooooo 1930 8)

[ Voor 18% gewijzigd door Infinitive op 21-06-2007 00:08 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
xx77qq schreef op woensdag 20 juni 2007 @ 23:43:
[...]

Okay, geef eens 10 keywords van C# die verkeerde common practice zijn. En geef eens een aantal goto-gevallen die onnodig en lelijk zijn (code van vandaag de dag als het kan)?
Ok, verzin eens 10 unmanaged code keywords voor C# in combinatie met een simpel ( calculator bijv ) Windows GUI programma. Alles wat beginners in unmanaged code doen ( omdat ze het vroeger zo aangeleerd hebben in een andere programmeertaal ) is verkeerd common practice.

Och tja, ik vermoed dat je in C# bedoelt voor de voorbeelden, maar die kan ik als je echt wil morgen wel opzoeken, maar kijk zelf eens rond naar beginners scriptjes / programma's. Het ging mij niet zozeer om de aantallen, maar meer om het feit dat er zat dingen zijn die in programmeertalen wel zitten maar die alleen met goed nadenken gebruikt moeten worden, bijv assembly kan je volgens mij nog steeds in de meeste programmeertalen kwijt, maar het is alleen handig als je iets echt snel gedaan wilt hebben met 100% controle van de code en op een specifiek platform. Dus als je iets echt op een AMD 3300 wilt hebben draaien dan kan je asm gebruiken, moet het op een AMD 3300 en ook op een Pentium II draaien dan is het verkeerde common practice om asm te gebruiken.

Maar voor vanavond. Welterusten

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

xx77qq schreef op woensdag 20 juni 2007 @ 22:16:
[...]


Als goto zo evil zou zijn waarom zit 'ie dan in de definitie van C# ?
Heb je überhaupt gelezen wat je zojuist gequote hebt? Overigens zit het niet in Java, go figure.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • xx77qq
  • Registratie: Januari 2004
  • Niet online
Je voorbeelden spreken voor zich, echter er zijn gevallen waarin je in een innerloop niet zomaar een return wilt gebruiken, maar eerst langs een exit point wilt gaan. Multilevel conditionals zoals in Java vangen dat probleem af, anders is een goto wel zo fraai.

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
xx77qq schreef op donderdag 21 juni 2007 @ 08:21:
[...]


Je voorbeelden spreken voor zich, echter er zijn gevallen waarin je in een innerloop niet zomaar een return wilt gebruiken, maar eerst langs een exit point wilt gaan. Multilevel conditionals zoals in Java vangen dat probleem af, anders is een goto wel zo fraai.
Volgens mij ga ik je niet overtuigen van je ongelijk. Maar goed, succes met de goto's, ik hoop dat ik nooit aan je code hoef te zitten...

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

xx77qq schreef op donderdag 21 juni 2007 @ 08:21:
[...]


Je voorbeelden spreken voor zich, echter er zijn gevallen waarin je in een innerloop niet zomaar een return wilt gebruiken, maar eerst langs een exit point wilt gaan.
Je bedoelt een try/finally in Java of C#, of RAII in C++ mbv een destructor? Die dingen zijn nog eens exception-safe ook, goto's niet.

[ Voor 11% gewijzigd door .oisyn op 21-06-2007 11:21 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Jewest
  • Registratie: Juni 2007
  • Laatst online: 15:47
Stomme opmerking misschien..
maar waarom check je niet gewoon of je pointer != NULL is?

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
TreeNode selectedTreeNode = null;
for (int i = 0; i < treeTableGepland.TreeModel.GetChildCount(null); i++)
{
   if(selectedTreeNode != NULL)
  {

     TreeNode node = (TreeNode)treeTableGepland.TreeModel.GetChild(null, i);
     foreach (TreeNode node2 in node.Nodes)
     {
       if(selectedTreeNode != NULL)
       { 
        if (node2.Tag as CustomActivity == activity)
        {
            selectedTreeNode = node2;
            goto NodeFound; // Impopulaire goto
        }
     }
    }
}

if (selectedTreeNode != null)
{
    treeTableGepland.ExpandRow(selectedTreeNode.Parent);


Kan ergens een haakje vergeten zijn...

[ Voor 0% gewijzigd door een moderator op 21-06-2007 11:30 . Reden: code tags toegevoegd... ]

Flickr
Canon 7D + Glas + Licht
Komt het rot over dan bedoel ik het anders en taalfouten zijn inbegrepen.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

je wilt checken op ==null, niet !=NULL. En die goto kun je dan natuurlijk ook wel weghalen. En als je dan in de inner loop een break zet, dan hoeft die tweede if niet, en bovendien kun je de buitenste if ook weghalen door de check in de for-conditie te doen. En hey, dan heb je exact de code zoals die van Grijze Vos in de eerste reactie in de draad.

[ Voor 80% gewijzigd door .oisyn op 21-06-2007 11:38 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • EfBe
  • Registratie: Januari 2000
  • Niet online
In C# is goto in sommige switch / case constructies nodig, omdat case niet een fall-through support, dus je kunt ranzige paden krijgen met goto maar soms moet dat of je moet veel code dupliceren in verschillende case clauses.

Goto in routines om control flow te bepalen is veelal niet zo nuttig omdat de code niet echt onderhoudbaar wordt. Maar echt slecht.... tja, dat is subjectief denk ik. Ik classificeer het geneuzel over goto in dezelfde categorie als de discussie dat je maar 1 exit point mag hebben in een method: Je wordt het nooit eens en het is tijdverknoeien.

* EfBe gebruikt nooit goto's omdat ze nooit nodig blijken. Wel meerdere exit points per method. :)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • mr_taipan
  • Registratie: Februari 2002
  • Laatst online: 03-12-2024
Ik heb een keer een oubollige manager gehad die een .net team moest managen. Tijden de eerste vergadering had hij het maar over goto sub. Het was moeilijk uit te leggen dat dat al 10 jaar niet meer bestond.

Vlak daarna heb ik voor mij de legendarische code geschreven

C#:
1
2
3
4
5
6
7
8
9
10
11
switch(value)
{
     case 0:
       //doe iets
       goto sub;
     case 1:
       //doe iets
       goto sub;
}

sub:


_/-\o_

[ Voor 12% gewijzigd door mr_taipan op 21-06-2007 15:00 ]


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Kent C# geen breaks om uit je switch te springen?

(had je baas het btw niet over 'gosub' ? Dat is de Basic voorloper van procedures.)

[ Voor 47% gewijzigd door Grijze Vos op 21-06-2007 15:30 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • mr_taipan
  • Registratie: Februari 2002
  • Laatst online: 03-12-2024
Volgens mij gebruikte hij echt het woord goto.

En natuurlijk heeft c# break; maar ik vond het wel een mooie constructie om goto sub te gebruiken >:)

  • xx77qq
  • Registratie: Januari 2004
  • Niet online
.oisyn schreef op donderdag 21 juni 2007 @ 11:20:
[...]

Je bedoelt een try/finally in Java of C#, of RAII in C++ mbv een destructor? Die dingen zijn nog eens exception-safe ook, goto's niet.
Mee eens, theoretisch klopt het wat je zegt, echter als ik lappen code zie die die te pas en toe onpas exception handling doen dan wordt dat er niet duidelijker en of leesbaarder op. En dan bedoel ik real-life software.
Voor mij is de expressiviteit van code een hoop waard. In mijn geval is het gebruik van goto daarmee soms gerechtvaardigd. Nog beter zou het zijn als de taal wat extra voorzieningen treft om de code weer expressiever te maken met behoud van robuustheid.

Professioneel heb ik delen van code geschreven voor oa. 24x7 machines die, zo ik laatst hoorde van een oude collega, nog steeds prima draaien ergens in China. Wat minder lang geleden eveneens 24x7 voor de security en tegenwoordig in apparaatjes die het gewoon moeten doen. Allemaal bevatten ze wel wat goto constructies en ze hebben me (nog niet) gebeten. Er zullen ongetwijfeld bugs inzitten, maar de kans dat die door een goto worden verzoorzaakt lijkt me erg klein.
(genoeg opgeschept, maar ik moest het even kwijt)

Als je goto niet vertrouwd of ontzettend ouderwets vind dan moet je 'm vooral niet gebruiken. Liever geen goto dan een verkeerde goto, maar voor mij geldt liever een goto dan 10 extra regels verbose code om hetzelfde te bereiken.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

xx77qq schreef op donderdag 21 juni 2007 @ 23:48:

Mee eens, theoretisch klopt het wat je zegt, echter als ik lappen code zie die die te pas en toe onpas exception handling doen dan wordt dat er niet duidelijker en of leesbaarder op.
Maar dat is echter een heel andere discussie en heeft weinig te maken met het al dan niet gebruik van goto :). Punt is dat exception-safe programming weldegelijk belangrijk is, en goto helpt daar doorgaans niet bij.
In mijn geval is het gebruik van goto daarmee soms gerechtvaardigd.
Hence mijn opmerking over de definitie van "evil". Het betekent niet dat je het nooit en te nimmer moet gebruiken. Er zijn weldegelijk gevallen waarin het het beste alternatief is, maar feit blijft wel dat die gevallen schaars zijn en een gestructureerd alternatief meestal beter is.
Wat minder lang geleden eveneens 24x7 voor de security en tegenwoordig in apparaatjes die het gewoon moeten doen. Allemaal bevatten ze wel wat goto constructies en ze hebben me (nog niet) gebeten. Er zullen ongetwijfeld bugs inzitten, maar de kans dat die door een goto worden verzoorzaakt lijkt me erg klein.
Dat een applicatie geen bugs bevat is nog geen garantie voor goed softwaredesign ;). "Hey, it works" is natuurlijk niet echt een valide argument.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • OxiMoron
  • Registratie: November 2001
  • Laatst online: 08-07 14:27
goto = bad

verneukt de flow van je programma..
Dat is reden genoeg om het gewoon NIET te gebruiken.

Albert Einstein: A question that sometime drives me hazy: Am I or are the others crazy?


  • Sjaaky
  • Registratie: Oktober 2000
  • Laatst online: 06-11 13:54
Waar het woordje 'goto' wel mag voorkomen (imho) is een expliciete fallthrough in een switchstatement:
code:
1
2
3
4
5
6
7
8
9
10
11
switch (a)
{
    case 1:
        //doe iets
        goto case 2;
    case 2:
        //doe iets anders
        break;
    default:
        break;
}

  • Ontspannen
  • Registratie: Februari 2007
  • Laatst online: 11-10 10:33
= bad: 8)7
OxiMoron schreef op vrijdag 22 juni 2007 @ 13:14:
goto = bad;

verneukt de flow van je programma..
Dat is reden genoeg om het gewoon NIET te gebruiken.
:+

Verwijderd

Sjaaky schreef op vrijdag 22 juni 2007 @ 13:19:
Waar het woordje 'goto' wel mag voorkomen (imho) is een expliciete fallthrough in een switchstatement:
code:
1
2
3
4
5
6
7
8
9
10
11
switch (a)
{
    case 1:
        //doe iets
        goto case 2;
    case 2:
        //doe iets anders
        break;
    default:
        break;
}
Maar een expliciete fallthrough heeft geen nut boven een impliciete fallthrough (?). Je kan beter een regel commentaar toevoegen om het te verduidelijken.

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op vrijdag 22 juni 2007 @ 13:57:
[...]


Maar een expliciete fallthrough heeft geen nut boven een impliciete fallthrough (?). Je kan beter een regel commentaar toevoegen om het te verduidelijken.
Expliciete fallthrough is in C# 2.0 verplicht als je fallthrough wilt hebben aangezien impliciete fallthrough niet meer kan.

Op zich vindt ik het wel 'jammer' dat ze dat met goto opgelost hebben. Het zou mischien eleganter geweest zijn om een tegenhanger van break te introduceren. Dus dat je in plaats van break gewoon continue plaatst.

Dus iets als het volgende. Dan wordt je ook niet zo uitgenodigd om stiekum toch nog naar een ander label te springen. Als je dat echt zou willen zou je altijd nog goto kunnen gebruiken.
C#:
1
2
3
4
5
6
7
8
9
10
11
switch( x )
{
       case 1:
            // doe wat
            continue; //Expliciete fallthrough
       case 2:
            // doe wat
            // En hier dan een compiler error omdat implicit fallthrough niet mag
       default:
            break;
}

[ Voor 27% gewijzigd door Woy op 22-06-2007 14:08 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:59
De goto-oplossing van C# vind ik opzich niet lelijk, want nu kun je ook naar een case springen die pas later komt. Hier zou ik hem zelf nog wel eens kunnen toepassen, maar met een goto naar een label springen is wel erg fout. Je code wordt daar niet echt duidelijker op. Maar een "goto case" zou ik nog wel kunnen begrijpen.

[ Voor 59% gewijzigd door Marcj op 22-06-2007 14:17 . Reden: quote is overbodig :) ]


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op vrijdag 22 juni 2007 @ 13:57:
[...]


Maar een expliciete fallthrough heeft geen nut boven een impliciete fallthrough (?). Je kan beter een regel commentaar toevoegen om het te verduidelijken.
C# ondersteunt geen fall through behalve:
case 1:
case 2:
..
case 3:

etc.

dus zodra een case clause code heeft, heb je geen fall through en moet je goto gebruiken wil je code van de ene clause naar de andere laten flowen.

Ik heb die verplichte break crap nooit begrepen: fall through is er niet, en je MOET break; erneer zetten.. De reden hiervooris ook zo bezopen "Dan voelen C++ programmeurs zich beter thuis", yeah so what... C# != C++

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mja, er is wel wat bij voor te stellen. Vrijwel elke C-achtige taal (C, C++, Java, ...) met het switch statement doet het op de C manier met fallthrough. Aan de syntax van de switch in C# blijkt niets dat de fallthrough in C# niet gebeurt. Exact dezelfde code krijgt ineens een andere betekenis. Je hebt gelijk dat die break redundant is, maar zo heel raar vind ik het niet dat het verplicht is (de vraag is echter wel: waarom de fallthrough niet gewoon impliciet laten zijn zoals in alle andere talen?)

In C+ mag de goto naar case label overigens weer niet, maar wat in C++ wel mag:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void foo(int f)
{
    int i = 0;

    switch(f)
    {
    case 0:
        for (i = 0; i < 4; i++)
        {
            std::cout << "A" << std::endl;

    case 1:
            std::cout << "B" << std::endl;

    case 2:
            std::cout << "C" << std::endl;
    
    case 3:
            std::cout << "D" << std::endl;
        }
    }
}


Handig om zonder goto naar het midden van de eerste iteratie van een loop te springen 8)7

[ Voor 10% gewijzigd door .oisyn op 22-06-2007 15:00 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

@.oisyn:

Gefeliciteerd! Dermate fraaie staaltjes van misleidende spaghetti-code kom ik maar zeer zelden tegen. Is dit een door jezelf voor dit topic geconstrueerde demo-case, of ben je dit in real life tegengekomen?

Slightly off_topic: je hebt hiermee mijn humeur geen goed gedaan. Dit doet me namelijk weer terugdenken aan de invoering van de eerste C++ standaard, bijna 10 jaar geleden. Het std-committee heeft toen een aantal in (bepaald niet alleen) mijn ogen twijfelachtige beslissingen genomen, zoals de verandering van de scope van een in een for-statement gedefiniëerde variabele, en het niet meer toestaan van het initialiseren van een const-ref met een non-const rvalue (zoals een temporary object als actuele parameter). Zeker gezien de argumenten, die ik (wij) ronduit onvoldoende vond(en): beide beslissingen braken helaas enorm veel code, en je hebt imho nogal sterke argumenten nodig als je zoiets door wilt voeren. Want C++ werd op dat moment al wel op grote schaal gebruikt.
En dan kom jij met de bovenstaande showcase aanzetten - als ze dan tóch de beslissing namen bestaande C-code op punten te breken, waarom hadden ze dát (het is natuurlijk in feite een goto naar een inner block zonder by-passing van geïnitialiseerde variabelen) nou niet uit de taal gesloopt? Gemiste kans dus.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op vrijdag 22 juni 2007 @ 15:52:
@.oisyn:

Gefeliciteerd! Dermate fraaie staaltjes van misleidende spaghetti-code kom ik maar zeer zelden tegen.
Gelukkig maar :). Same here trouwens.
Is dit een door jezelf voor dit topic geconstrueerde demo-case, of ben je dit in real life tegengekomen?
Het was een demonstratie van wat de syntax toelaat. Toen ik het voor het eerst zag (ergens op een internetpagina oid, een stukje code van 20+ jaar oud) was ik er verrast van dat het überhaupt kon. Zoiets verzin je toch niet :)
Het std-committee heeft toen een aantal in (bepaald niet alleen) mijn ogen twijfelachtige beslissingen genomen, zoals de verandering van de scope van een in een for-statement gedefiniëerde variabele, en het niet meer toestaan van het initialiseren van een const-ref met een non-const rvalue (zoals een temporary object als actuele parameter). Zeker gezien de argumenten, die ik (wij) ronduit onvoldoende vond(en): beide beslissingen braken helaas enorm veel code, en je hebt imho nogal sterke argumenten nodig als je zoiets door wilt voeren. Want C++ werd op dat moment al wel op grote schaal gebruikt.
C++ was echter verre van gestandaardiseerd, en iedere lapswans van een implementer kon er dus z'n eigen draai aan geven. Je kon er dus donder op zeggen dat code sowieso hoe dan ook ging breken, en ik moet zeggen dat ik het zelf (ik was destijds niet zo bewust met C++ bezig dus ik heb verder geen ervaring met de daadwerkelijke overgang) eens ben met de genomen beslissingen. Een temporary koppelen aan een non-const ref is vragen om problemen, en waarom zou een in een for-statement gedefinieerde variabele niet alleen in de betreffende scope zichtbaar zijn?
Puur het argument om het niet te doen omdat er code bestaat die toch al niet aan geen enkele standaard voldoet vind ik niet echt een valide argument om het maar niet te doen. En als de implementors de oude code willen blijven toestaan dan kunnen ze dat gewoon doen met een compiler-optie, zodat de code toch niet breekt.

Ik snap dat backwards-compatibility een belangrijke issue is in deze, maar het remt natuurlijk ook de ontwikkeling en op een gegeven moment moeten er knopen doorgehakt worden.
En dan kom jij met de bovenstaande showcase aanzetten - als ze dan tóch de beslissing namen bestaande C-code op punten te breken, waarom hadden ze dát (het is natuurlijk in feite een goto naar een inner block zonder by-passing van geïnitialiseerde variabelen) nou niet uit de taal gesloopt? Gemiste kans dus.[/small]
Maar hier ligt de zaak heel anders. C was namelijk al in '90 gestandaardiseerd, en die compatibiliteit was iig gewenst.

Maar goed, enorm offtopic dit allemaal ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • DaCoTa
  • Registratie: April 2002
  • Laatst online: 30-11 21:02
.oisyn schreef op vrijdag 22 juni 2007 @ 14:57:
In C+ mag de goto naar case label overigens weer niet, maar wat in C++ wel mag:
C++:
1
2
3
void foo(int f){
knip
}

Handig om zonder goto naar het midden van de eerste iteratie van een loop te springen 8)7
Ik tuur al een tijdje naar de code, maar wat gebeurd er nu als je foo(2) aanroept? Krijg je dan
CDABCDABCDABCD? Of CDCDCDCD?

  • user109731
  • Registratie: Maart 2004
  • Niet online
DaCoTa schreef op vrijdag 22 juni 2007 @ 16:36:
[...]

Ik tuur al een tijdje naar de code, maar wat gebeurd er nu als je foo(2) aanroept? Krijg je dan
CDABCDABCDABCD? Of CDCDCDCD?
Ik denk zelf CD? Volgens mij word direct naar label 2 gejumpt, en die 'valt door' naar 3 :)
De for loop hangt alleen onder case 0, en daar komtie helemaal niet langs. AFAIK, want je weet het maar nooit met zulke code ;)

edit: of aan het eind van het for-block word de conditie geavalueerd, en dan zou het de eerste zijn... De tweede lijkt me niet omdat je de switch maar eenmalig passeert denk ik.

[ Voor 16% gewijzigd door user109731 op 22-06-2007 16:42 ]


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 17:20

Janoz

Moderator Devschuur®

!litemod

In dat geval wordt het nog spannend wanneer je i op 2 initialiseert :).

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

DaCoTa schreef op vrijdag 22 juni 2007 @ 16:36:
[...]

Ik tuur al een tijdje naar de code, maar wat gebeurd er nu als je foo(2) aanroept? Krijg je dan
CDABCDABCDABCD? Of CDCDCDCD?
Die eerste ja. Je jumpt in het midden naar de eerste iteratie, daarna loopt ie gewoon verder en dus start je in de tweede iteratie gewoon weer in case 0 :)

Een usecase waar het nuttig zou kunnen, bijv. de implementatie van PHP's implode():

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template<class InputIt>
std::string implode(InputIt begin, InputIt end, const std::string & delim = ",")
{
    if (begin == end)
        return;

    std::ostringstream resultstream;
    switch(true)
    {
    case false:
        while (begin != end)
        {
            resultstream << delim;

    case true:
            resultstream << *begin;
            ++begin;
        }
    }

    return resultstream.str();
}


mooi is anders :P, en uiteindelijk is het natuurlijk gewoon een verkapte vorm van goto:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<class InputIt> 
std::string implode(InputIt begin, InputIt end, const std::string & delim = ",") 
{
    if (begin == end)
        return;

    std::ostringstream resultstream; 
    goto start;

    while (begin != end) 
    { 
        resultstream << delim; 

start:
        resultstream << *begin; 
        ++begin; 
    } 

    return resultstream.str(); 
}

[ Voor 84% gewijzigd door .oisyn op 22-06-2007 17:11 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1