C# Switch case goto Default mit Syntax Error!

Yuuri schrieb:
So wie das aussieht, hättest du auch einfach das goto weglassen können, wenn nachfolgende Zweige sowieso abgearbeitet werden sollen. Das goto ist überflüssig. Ein case-Zweig endet ja nur, wenn es auf ein break; trifft.

Nein eben nicht .. Siehe switch (C#-Referenz)

Im Gegensatz zu C++ lässt C# nicht zu, dass die Ausführung von einem Switch-Abschnitt zum nächsten fortgesetzt wird. Im folgenden Code wird ein Fehler verursacht.

z.B: Das Steuerelement kann nicht von einer case-Bezeichnung ("case 20:") zur nächsten fortfahren.

In C# muss man einen Caseblock mit break, goto case, return oder throw abschliessen.
 
@lynxx: Warum machst du das nicht mit einer for-Schleife?

Code:
short k = 0;
for (int i = lPart; i > 0; i--)
    pixel[t + k] += curField[u + k++];

Oder hab ich jetzt was übersehen?
 
schlzber schrieb:
@lynxx: Warum machst du das nicht mit einer for-Schleife?

Code:
short k = 0;
for (int i = lPart; i > 0; i--)
    pixel[t + k] += curField[u + k++];

Oder hab ich jetzt was übersehen?
Weil es langsamer ist .. Der Block wird von 64 Workern verwendet, für "einen Durchlauf" wird dieser Part bis zu 11.256.000 mal angesprungen. Das dann jedesmal ein neuer Zähler gesetzt und nach jedem addierten Pixel geprüft werden muss ob das Ende erreicht worden ist macht dann schon einen großen Unterschied. Ausserdem ist das nur der X-Teil der Schleife:
Code:
for (short j = 0; j < lPartStar; ) {
  short u = (short)(lPartStar * j++);
  int t = multab[j] + pos;
  short k = 0;
  switch (lPartStar) {
    case 20: pixel[t + k] += useField[u + k++]; goto case 19;
    case 19: pixel[t + k] += useField[u + k++]; goto case 18;
    case 18: pixel[t + k] += useField[u + k++]; goto case 17;
    case 17: pixel[t + k] += useField[u + k++]; goto case 16;
    case 16: pixel[t + k] += useField[u + k++]; goto case 15;
    case 15: pixel[t + k] += useField[u + k++]; goto case 14;
    case 14: pixel[t + k] += useField[u + k++]; goto case 13;
    case 13: pixel[t + k] += useField[u + k++]; goto case 12;
    case 12: pixel[t + k] += useField[u + k++]; goto case 11;
    case 11: pixel[t + k] += useField[u + k++]; goto case 10;
    case 10: pixel[t + k] += useField[u + k++]; goto case 9;
    case 9: pixel[t + k] += useField[u + k++]; goto case 8;
    case 8: pixel[t + k] += useField[u + k++]; goto case 7;
    case 7: pixel[t + k] += useField[u + k++]; goto case 6;
    case 6: pixel[t + k] += useField[u + k++]; goto case 5;
    case 5: pixel[t + k] += useField[u + k++]; goto case 4;
    case 4: pixel[t + k] += useField[u + k++]; goto case 3;
    case 3: pixel[t + k] += useField[u + k++]; goto case 2;
    case 2: pixel[t + k] += useField[u + k++]; goto case 1;
    case 1: pixel[t + k] += useField[u + k]; break;
  }
}
Also lPart zu ändern ist auch da eher hinderlich.
Die Vars heissen jetzt lPartStar & useField weil wegen Clipping an den Rändern kleinere Objekte genommen werden ..
Nebenbei interessant das:
pixel[t + k] += useField[u + k++];
int + shortaddition, short + shortaddition, short erhöhen

schneller ist als

pixel[t++] += useField[u++];
int erhöhen, short erhöhen
 
@toeffi lol, ich weiss das 10% des Codes 90% der Rechenzeit verbrauchen, da stecke ich dann aber auch viel Mühe rein.

schlzber schrieb:
@Lynxx: Hast du das denn mal nachgemessen und verglichen? Falls ja, und es mit switch signifikant schneller geht, musst du wohl in den sauren Apfel beißen und Lesbarkeit für Performance opfern.

Klar hab ich gemessen, ich lasse Stopwatch (Stopwatch stop = new Stopwatch(); stop.Start();...) laufen und addiere die vergangenen Millisekunden und bilde am Ende über die Anzahl der Durchläufe das Mittel. Das Ergebnis ist nach einigen Sekunden sehr genau und unterliegt fast keinen Schwankungen.

Und da dieser Part den Großteil der Rechnenzeit verbraucht habe ich auch schon soviel Arbeit da reingesteckt und verschiedene Methoden/Addressierungsarten etc probiert, bzw die Routine auf Multithreading umgestellt und lasse 64 Worker gleichzeitig drauf los.
Klar lasse ich das so, nur als Kommentar "//for (short k = 0; k < lPart; pixel[t + k] += useField[u + k++]);" darüber damit auch später noch klar ist was dieses Konstrukt soll ..

Es ging hier aber eigentlich darum ob goto in Case ok ist oder nicht, ich würde sagen ja - weil man ja nur zu anderen Case-Blöcken springt - und es in C# gar nicht möglich ist aus deinem Case-Block "rauszulaufen" (Ausnahme: leere Case-Blöcke).
 
Zuletzt bearbeitet:
Also der Code scheint echt nicht schneller in C# hinzubekommen sein...
Aber - und da muss ich zustimmen - entscheidet nicht der Einsatz von GOTO ob der Code gut oder schlecht les-/wartbar wird, sondern immer noch der Programmierer...

So lange man keinen Unfug mit den GOTOs betreibt gibt es nicht wirklich was entgegenzusetzen.Aber das wäre wie wenn man einem C++-Programmierer sagt "Mit Zeiger kann man einiges falsch machen, also lass es...". Klar, ich vermisse GOTOs nicht, und ja, es lässt sich im Grunde auch alles ohne sie realisieren.

Und die GOTOs in diesem Beispiel sind auch keine klassischen GOTOs mit den bekannten Nachteilen/Problemen...
 
@lynxx: Hast du mal probiert, den Abschnitt als unsafe zu deklarieren? Dann kannst du auf pixel und useField über Zeiger zugreifen und die Indexüberprüfungen bei jedem Arrayzugriff fallen weg, was bei zwei Indizierungen pro Zuweisung nicht unerheblich sein sollte.

http://msdn.microsoft.com/de-de/library/t2yzs44b.aspx
 
Zuletzt bearbeitet:
@1668mib

Also versuch ohne goto aus eine 3x Schleife mit nur einem Befehl rauszukommen... also wirklich nur einzeilig ohne bool variableüberprüfung! :D

Code:
foreach(var a in List)
{
    foreach(var b in a.List)
    {
        foreach(var c in b.List)
        {
            ///Irgendwann mal
            goto RausHier;
        } 
    } 
}

RausHier:
//Code

OK... zu den 64 Threads.... wie sieht es mit CPU Last aus? 64 Threads die gleichzeitig laufen sind heavy.
 
Zuletzt bearbeitet:
64 Threads können nur dann Gleichzeitig laufen wenn du 64 Kerne hast. Wenn lynxx 64 Kerne hat, dann kann er das machen aber es ist nicht möglich wenn ich nur 2 oder 4 Kerne habe. Das heißt die anderen 60 oder 62 müssen eh warten bis die CPU Rechenzeit für sie abgibt.
 
Ih schlage vor Objektorientierung zu nutzen.

Am besten eine SNMP Grundklasse, welche jede Menge Templatemethoden enthält (Im Prinzip für jede Abweichung zwischen den SNMP-Versionen eine solche Methode).

Dann implementiert diese Grundklasse das Verhalten für Version1+2.

Für Version 3 leitet man sich von der Grundklasse ab und überschreibt diejenigen Templatemethoden, welche ein anderes Verhalten aufweisen.
 
roker002 schrieb:
OK... zu den 64 Threads.... wie sieht es mit CPU Last aus? 64 Threads die gleichzeitig laufen sind heavy.

toeffi schrieb:
64 Threads können nur dann Gleichzeitig laufen wenn du 64 Kerne hast. Wenn lynxx 64 Kerne hat, dann kann er das machen aber es ist nicht möglich wenn ich nur 2 oder 4 Kerne habe. Das heißt die anderen 60 oder 62 müssen eh warten bis die CPU Rechenzeit für sie abgibt.

20 Threads wären auch kaum langsamer, aber da 64 nicht langsamer ist hab ich es so hoch eingestellt. :p CPU-Last ist nur so bei 60-70% (i2500k@4.5Ghz), ich protokolliere auch die längste Zeit die ein Thread gebraucht hat (momentan 43ms) und die Durchschnittszeit eines einzelnen Threads: 3ms, das warten auf die Threads dauert durchschnittlich 63ms, also müssen so um die 20 gleichzeitig aktiv sein. Unsafe muss ich mal probieren ..

Edit:
Unsafe hat die Wartezeit auf 57ms gedrückt, also 6ms schneller - dafür siehts jetzt noch kryptischer aus. :evillol:
PHP:
for (short j = 0; j < lPartStar; ) {
  int* t = pixelptr + multab[j] + pos;
  byte* u = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(useField, lPartStar * j++);
  switch (lPartStar) {
    case 20: *t++ += *u++; goto case 19;
    case 19: *t++ += *u++; goto case 18;
    case 18: *t++ += *u++; goto case 17;
    case 17: *t++ += *u++; goto case 16;
    case 16: *t++ += *u++; goto case 15;
    case 15: *t++ += *u++; goto case 14;
    case 14: *t++ += *u++; goto case 13;
    case 13: *t++ += *u++; goto case 12;
    case 12: *t++ += *u++; goto case 11;
    case 11: *t++ += *u++; goto case 10;
    case 10: *t++ += *u++; goto case 9;
    case 9: *t++ += *u++; goto case 8;
    case 8: *t++ += *u++; goto case 7;
    case 7: *t++ += *u++; goto case 6;
    case 6: *t++ += *u++; goto case 5;
    case 5: *t++ += *u++; goto case 4;
    case 4: *t++ += *u++; goto case 3;
    case 3: *t++ += *u++; goto case 2;
    case 2: *t++ += *u++; goto case 1;
    case 1: *t += *u; break;
  }
}
 
Zuletzt bearbeitet:
@roker002: Je nachdem was die Schleifen machen, kann man den Inhalt auch in eine Hilfsmethode auslagern... das würde sowieso der Philosophie, Methoden möglichst kurz zu halten und nur eine Aufgabe machen zu lassen entsprechen.
 
lynxx schrieb:
20 Threads wären auch kaum langsamer, aber da 64 nicht langsamer ist hab ich es so hoch eingestellt. :p CPU-Last ist nur so bei 60-70% (i2500k@4.5Ghz), ich protokolliere auch die längste Zeit die ein Thread gebraucht hat (momentan 43ms) und die Durchschnittszeit eines einzelnen Threads: 3ms, das warten auf die Threads dauert durchschnittlich 63ms, also müssen so um die 20 gleichzeitig aktiv sein. Unsafe muss ich mal probieren ..

Die Logik kann ich nicht ganz nachvollziehen. Wie stellst du dir vor, daß auf einer Maschine mit 2 physikalischen Kernen (und damit wahrscheinlich 4 logischen) 20 Threads gleichzeitig laufen sollen?

Darüber hinaus sind Konfigurationen mit mehr Threads als logischen Kernen prinzipiell Zeitverschwendung. Mehr Threads == mehr Overhead beim Scheduler. Mehr Threads bringen nur dann mehr, wenn es auch mehr Kerne gibt.
Ergänzung ()

roker002 schrieb:
@1668mib

Also versuch ohne goto aus eine 3x Schleife mit nur einem Befehl rauszukommen... also wirklich nur einzeilig ohne bool variableüberprüfung! :D

Code:
foreach(var a in List)
{
    foreach(var b in a.List)
    {
        foreach(var c in b.List)
        {
            ///Irgendwann mal
            goto RausHier;
        } 
    } 
}

RausHier:
//Code


Wir wär's hiermit (pseudo-code)?

Code:
void doStuffWithList( ListType List )
{
    foreach(var a in List)
    {
        foreach(var b in a.List)
        {
            foreach(var c in b.List)
            {
                ///Irgendwann mal
                //goto RausHier;
                return;
            } 
        } 
    }
}
 
Zuletzt bearbeitet:
@antred, ja es geht so, wenn du komplett aus der Methode springst... aber dann musst du den code danach auslagern.

Verwende fast nie den goto, weil ich kein Bedarf hatte. Soweit ich weiss, ist es mein erster goto!

Wegen SNMP... der Befehl wurde vom Chef abgeflacht. Die Klasse ist geschrieben! Es ist aber nichts besonderes. Ich habe da schon aufgegeben was vollständiges auszudenken, was alle Fälle abdeckt, da es nur 2 fest Strukturen für die Benachrichtigung gibt.

@Lynxx

Es währe viel Stromsparrender wenn du 2 echte CPUs nehmen würdest anstatt eine zu übertakten. Je höher der Takt desto niedriger ist die Effizienz deines System zum Stromverbrauch :D
Es wird mehr Strom in die Hitze umgewandelt als es für den Prozessor benötigt wird, leider!
 
roker002 schrieb:
@antred, ja es geht so, wenn du komplett aus der Methode springst... aber dann musst du den code danach auslagern.

Eben, das oben sollte ja der ausgelagerte Code sein. ;) Wobei ich am Auslagern nichts negatives sehe. Dadurch würde die ursprüngliche Funktion ein paar Zeilen kürzer, und das ist doch eigentlich nie verkehrt.
 
Zurück
Oben