Vezérlőpult
D3. Túlterhelés, out és ref · Metódusok

D blokk · Metódusok · 3. tananyag

Túlterhelés, opcionális paraméter, out és ref

A D2-vel a fejléc majdnem teljes — de három kérdés nyitva maradt. Mi van, ha ugyanarra a műveletre többféle bemenettel is szükség van? Ha egy paraméternek majdnem mindig ugyanaz az értéke? És hogyan ad vissza egy metódus két eredményt — ahogy a TryParse teszi a B6 óta? Ma az out titka is megfejtésre kerül.

1 tanóraoverload · alapértékout · ref

Tanulási célok

1Túlterhelés: egy név, több alak

A D1–D2-ben vonalhúzó metódusokat írtunk — többfélét, több néven. Pedig mind ugyanazt csinálja, csak más bemenettel. C#-ban adhatjuk nekik ugyanazt a nevet:

Vonal();                 // alapvonal
Vonal(50);               // hosszabb
Vonal('=', 20);          // más jelből

void Vonal()
{
    Vonal('-', 30);      // a rövid alak a teljeset hívja — nincs másolás!
}

void Vonal(int hossz)
{
    Vonal('-', hossz);
}

void Vonal(char jel, int hossz)
{
    for (int i = 0; i < hossz; i++)
    {
        Console.Write(jel);
    }
    Console.WriteLine();
}
ℹ️ RÉGI ISMERŐS

A Console.WriteLine is túlterhelt: hívtad már üresen (üres sor), stringgel, számmal — és mindig „tudta”, mit tegyen. Most már azt is tudod, miért: a fordító a szignatúrák közül választott.

2Opcionális paraméter: az alapértelmezett érték

A háromalakú vonalhúzó egyetlen metódussal is megoldható:

void Vonal(char jel = '-', int hossz = 30)
{
    for (int i = 0; i < hossz; i++)
    {
        Console.Write(jel);
    }
    Console.WriteLine();
}

Vonal();                 // '-' jelből 30
Vonal('=');              // '=' jelből 30
Vonal('=', 20);          // '=' jelből 20
💡 TÚLTERHELÉS VAGY OPCIONÁLIS?

Ha az alakok csak alapértékekben térnek el: opcionális paraméter (egy törzs). Ha más a viselkedésük vagy más típusú a bemenetük: túlterhelés.

3Az out: a TryParse titka megfejtve

A D2-ben rögzítettük: a metódus másolatot kap, a hívó változójához nem nyúl. Az out ez alól ad szabályozott kivételt: az out paraméteren keresztül a metódus a hívó változójába ír.

Most már megírhatjuk a saját „TryParse-szabású” metódusunkat:

if (BiztonsagosOsztas(10, 3, out int hanyados))
{
    Console.WriteLine($"Az eredmény: {hanyados}");
}
else
{
    Konzol.Hiba("Nullával nem osztunk!");
}

bool BiztonsagosOsztas(int a, int b, out int eredmeny)
{
    if (b == 0)
    {
        eredmeny = 0;        // out-nak MINDEN úton értéket kell kapnia
        return false;
    }
    eredmeny = a / b;
    return true;
}

És ezzel a B6-os rejtély teljesen megoldva — olvasd el a fejlécet, ma már minden szava ismerős:

public static bool TryParse(string s, out int result)

4A ref: helyben módosítás

Az out-nál a metódus ad; a ref-nél a metódus a hívó meglévő értékét kapja meg és módosíthatja:

int pontszam = 80;
Bonusz(ref pontszam);
Console.WriteLine(pontszam);     // 90 — tényleg megváltozott!

void Bonusz(ref int ertek)
{
    ertek += 10;
}
⚠️ MIKOR MELYIK?

Az esetek túlnyomó részében egyik sem — az alapértelmezett út a return (D2): tiszta, követhető. Az out akkor jó, ha két kimenet kell (siker + eredmény, vagy két összetartozó érték); a ref ritka vendég — akkor, ha egy meglévő értéket tényleg helyben kell átírni (pl. csere).

Melyik eszközt választanád?

Túlterhelés, opcionális paraméter, out vagy ref — a helyzet dönt.

1 / 8Pontszám: 0
…

5Gyakori hibák

TünetMi történt?Mit tegyél?
CS0111: already defines a member … with the same parameter typeskét metódus azonos szignatúrávala paraméterlistának különböznie kell — a visszatérési típus nem számít bele
CS1737: Optional parameters must appear after all required parametersopcionális paraméter került a kötelezők eléaz = érték-es paraméterek a lista végére
CS0177: The out parameter … must be assignedvan kódútvonal, ahol az out nem kap értéketminden ágon adj értéket — a hibaágon is (pl. 0)
CS1620: Argument … must be passed with the 'out' keyworda hívásból lemaradt az out/ref kulcsszóírd ki a hívásban is: Metodus(out valtozo)
CS0165 a ref-es hívásnála ref-ként átadott változónak még nincs értékeref-hez inicializált változó kell (out-hoz nem)
a fordító „nem találja” a hívni kívánt alakot (CS1503)az argumentumok egyik túlterhelt alakra sem illeneknézd végig a szignatúrákat: melyikhez igazodnak a típusaid?

6Gyakorlat — a SzamotKer megtanul határok között kérdezni

  1. Nyisd meg az előző órai projektet (benne a D2-es Konzol.SzamotKer-rel).
  2. Írd meg a Konzol.cs-be a túlterhelt változatot: public static int SzamotKer(string kerdes, int min, int max) — addig kérdezzen újra, amíg a szám a határok közé nem esik (C5-ös do-while + C1-es feltétel), a hibaüzenet nevezze meg a határokat.
  3. A törzsben használd az egyparaméteres alakot: a számot azzal kérd be, és csak a tartományt ellenőrizd — DRY!
  4. Írd át a számkitalálót: int tipp = Konzol.SzamotKer("Tipped: ", 1, 100); — és próbáld ki tartományon kívüli számmal.
  5. Bónusz: adj a Konzol.Elvalaszto-nak opcionális paramétereket (char jel = '─', int hossz = 28).
  6. Commit: SzamotKer tulterheles min-max hatarokkal.
✅ ELLENŐRZŐ PONT

A SzamotKer mindkét alakja működik; betűre, rossz számra és tartományon kívüli értékre is újrakérdez; a kétparaméteres alak nem másolja a beolvasó ciklust.

7Feladatok

Gyakorló feladatok

⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás

D3.1⭐

Kétalakú üdvözlés: írj Udvozol() és Udvozol(string nev) metódust: az első általánosan köszön, a második név szerint. A paraméter nélküli hívja a paraméterest egy alapértelmezett szöveggel.

D3.2⭐⭐

Keret kétféleképpen: írd meg a szöveget bekeretező metódust ELŐSZÖR két túlterhelt alakkal (Keret(string szoveg) és Keret(string szoveg, char jel)), MAJD egyetlen opcionális paraméteres változattal. Melyik tetszik jobban? Kommentben indokold.

D3.3⭐⭐

Nagyobb, kétszer: írj int Nagyobb(int a, int b) ÉS double Nagyobb(double a, double b) metódust — a fordító a hívás alapján választ. Próbáld ki vegyes hívásokkal, és figyeld meg, mikor melyik fut.

D3.4⭐⭐

Időfelbontó: írj void Felbont(int osszMasodperc, out int perc, out int masodperc) metódust (B2-es / és %!), és írasd ki vele a 754 másodpercet perc:másodperc alakban.

D3.5⭐⭐⭐

Csere: írj void Csere(ref int a, ref int b) metódust a klasszikus háromváltozós cserével (B9.14 emléke!) — és mutasd meg egy rövid programban, hogy a hívó változói tényleg helyet cseréltek. Gondold végig: miért nem lehetne ezt return-nel megoldani?

8Önellenőrző kvíz

Ellenőrizd magad!

Minden kérdésnél egy válasz helyes. A végén pontszámot kapsz.

9Fogalomtár

FogalomJelentés
túlterhelés (overload)azonos nevű metódusok különböző paraméterlistával — a fordító a hívásból választ
szignatúraa metódus neve + paraméterlistája — ennek kell egyedinek lennie
opcionális paraméteralapértelmezett értékű paraméter (int hossz = 30) — a hívásból elhagyható
név szerinti argumentuma paraméter nevével címzett átadás: Vonal(hossz: 10)
outa metódus a hívó változójába ír — köteles minden úton értéket adni
refa metódus a hívó meglévő értékét kapja és módosíthatja
TryParse-mintabool visszatérés a sikerről + out paraméter az eredménynek

10Összegzés

  1. A túlterhelés azonos név — különböző szignatúra; a rövid alakok a legteljesebbet hívják, a munka egy helyen marad.
  2. Az opcionális paraméter alapértéket ad (= érték), a lista végén áll — alapérték-eltérésekre ez, viselkedés-különbségre túlterhelés.
  3. Az out a szabályozott kivétel az érték szerinti átadás alól: a metódus a hívó változójába ír, minden úton köteles értéket adni — ez a TryParse-minta: bool siker + out eredmény.
  4. A ref meglévő értéket módosít helyben — ritkán kell; az alapút mindig a return.
  5. A Konzol.SzamotKer tartomány-ellenőrzős alakkal bővült — a Mastermind bekérései készen állnak.
  6. Egy kérdés maradt a fejlécből: mit jelent pontosan a public static — és mi van a top-level programjaink mögött? A blokk zárófejezete megmutatja.