A goto utasítás a C nyelv öröksége. Feltétel nélküli ugró utasításként is szoktak rá hivatkozni. Arra jó, hogy a program futását egy másik helyre irányítsa át. A helyek megadása címkék segítségével történik. A címke egy azonosító, amely megfelel a változók névadásánál ismertetett szabályoknak és kettősponttal végződik.
A goto utasítás használatát az alábbi példa mutatja be:
using System;
namespace PeldaGoto
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Goto példa. Kilépés: CTRL+C");
eleje:
Console.WriteLine("Add meg a neved");
var nev = Console.ReadLine();
Console.WriteLine($"Szia {nev}!");
goto eleje;
}
}
}
A program kimenete valami hasonló lesz:
Goto példa. Kilépés: CTRL+C
Add meg a neved
Teszt
Szia Teszt!
Add meg a neved
Elek
Szia Elek!
Add meg a neved
A fenti kódrészlet bekéri a felhasználótól a nevét, majd kiírja azt formátumozottan a képernyőre. Ezt követően pedig az eleje címkéhez ugrik, ami a név bekérés előtt helyezkedik el. Könnyen belátható, hogy ez egy végtelenségig ismétlődő folyamat, amit programozásban végtelen ciklusnak neveznek.
Sok programozási könyvben a végtelen ciklust burkoltan a „sátán művének” igyekeznek beállítani és kerülendő dologként tartják számon. Ez részben igaz, de egy kiegészítéssel élnék, mivel kezdőként nem biztos, hogy mindenki érti, miért káros egy végtelen ciklus.
Az operációs rendszerünk amellett, hogy kommunikál velünk, több programot próbál meg a háttérben futtatni. Valóságban azonban kevesebb processzormag van a gépben, mint amennyi folyamat fut. Ezért az operációs rendszernek a programok között váltogatnia kell. Egyik programot leállítja, majd futtatja a következőt. Ezt a folyamatot addig ismétli, míg a számítógép és a rendszer fut. Programozói szemmel nézve ez ugyebár előre nem jelezhető időtartam. Akár futhat évekig is egy operációs rendszer újraindítás nélkül, ezért ezt a folyamatot legbelül egy végtelen ciklus végzi el. Ha a végtelen cikluson belül alkotunk egy ellenőrizetlen végtelen ciklust, akkor a külső, feladatváltó végtelenített ciklus nem fogja tudni rendesen végezni a dolgát. A váltó algoritmus megvalósításától függően két fő dolog történhet. Vagy az történik, hogy a programunk fog csak futni és semmi más, vagy a jobbik esetben „csak” kevesebb erőforrás jut a többi programnak. Jelen példakódban a programunk nem okoz különösebb kárt, mivel az adatbekérés külső interakció, ami blokkolja a program további végrehajtását.
Bizonyos szám felett könnyen bele lehet kavarodni a címkék és ugrások használatába, ami komoly biztonsági és egyéb hibákat eredményezhet. Ebből adódóan nem túlzottan ajánlja egy szakirodalom sem az alkalmazását. Azonban egy régi mondás szerint „Egy igazi programozó csak goto-t használ”. Illetve adódhat olyan eset, hogy egy goto használata igen hasznos lehet. Lényeg az, hogy gondoljuk át jól.
A goto nyelvi problémája véleményem szerint abból adódik C# esetén, hogy nincs hozzá formázási támogatás. Tehát a kódunkat magunknak kell megfelelően formázni, hogy lássuk, hogy hol kezdődik és végződik egy adott címke.
Belső megvalósításban a switch – case szerkezet goto utasításokra támaszkodik. Lényegében minden konstans értékből, ami a case után áll, címke fordul, amire egy ugrással a switch fog hivatkozni. Többek között ezért kell a break utasítást kitenni, mert a vezérlés folytatódna a következő case utasítással.
A break elhagyása C és C++ esetén nem okoz fordítási hibát, de általában nem szándékosan kerül lehagyásra. Többek között C# esetén ezért okoz fordítási hibát. Viszont mivel minden case címkére fordul, használhatunk goto-t arra, hogy a vezérlés egy másik case utasításra essen át.
Van az a mondás, miszerint „attól, hogy valamit megtehetünk, még nem biztos, hogy meg kell tennünk”. Ennek tipikus példája az alábbi kódrészlet, ami lefordul, viszont nem a legelegánsabb megoldás.
switch (a)
{
case 3:
b = 7;
goto case 4;
case 4:
c = 3;
break;
default:
b = 2;
c = 4;
break;
}