Megosztás a következőn keresztül:


Metódusok a C-ben#

A metódus egy utasítássorozatot tartalmazó kódblokk. Egy program a metódus meghívásával és a szükséges metódusargumentumok megadásával hajtja végre az utasításokat. A C#-ban minden végrehajtott utasítás egy metódus kontextusában történik.

Feljegyzés

Ez a cikk az elnevezett metódusokat ismerteti. A névtelen függvényekről további információt a Lambda-kifejezésekben talál.

Metódus szignatúrák

A metódusokat egy class, record, vagy struct deklarálásával adják meg a következőképpen:

  • Választható hozzáférési szint, például public vagy private. Az alapértelmezett érték private.
  • Választható módosítók, például abstract vagy sealed.
  • A visszaadott érték, vagy void ha a metódus nem rendelkezik ilyen értékkel.
  • A módszer neve.
  • Bármilyen metódusparaméter. A metódusparaméterek zárójelek közé vannak zárva, és vesszővel vannak elválasztva. Az üres zárójelek azt jelzik, hogy a metódus nem igényel paramétereket.

Ezek a részek együttesen alkotják a metódus aláírását.

Fontos

A metódus visszatérési típusa nem része a metódus szignatúrájának a metódus túlterhelése szempontjából. Ez azonban a metódus aláírásának része, amikor meghatározza a meghatalmazott és a metódus közötti kompatibilitást.

Az alábbi példa egy öt metódust tartalmazó osztályt Motorcycle határoz meg:

namespace MotorCycleExample
{
    abstract class Motorcycle
    {
        // Anyone can call this.
        public void StartEngine() {/* Method statements here */ }

        // Only derived classes can call this.
        protected void AddGas(int gallons) { /* Method statements here */ }

        // Derived classes can override the base class implementation.
        public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }

        // Derived classes can override the base class implementation.
        public virtual int Drive(TimeSpan time, int speed) { /* Method statements here */ return 0; }

        // Derived classes must implement this.
        public abstract double GetTopSpeed();
    }

Az Motorcycle osztály tartalmaz egy túlterhelt metódust. Drive Két metódusnak ugyanaz a neve, de a paraméterlistáik megkülönböztetik őket.

Metódushívás

A metódusok lehetnek példányok vagy statikusak. Objektum példányt kell létrehoznia ahhoz, hogy meghívjon egy példánymetódust azon a példányon; egy példánymetódus azon a példányon és annak adatain működik. Statikus metódus meghívásához hivatkozzon annak a típusnak a nevére, amelyhez a metódus tartozik; a statikus metódusok nem működnek a példányadatokon. Ha statikus metódust próbál meghívni egy objektumpéldányon keresztül, fordítóhiba jön létre.

A metódus meghívása olyan, mint egy mező elérése. Az objektum neve (ha példánymetódust hív meg) vagy a típus neve (ha static metódust hív meg), adjon hozzá egy pontot, a metódus nevét és zárójeleket. Az argumentumok a zárójelek között vannak felsorolva, és vesszővel vannak elválasztva.

A metódusdefiníció megadja a szükséges paraméterek nevét és típusait. Amikor egy hívó meghívja a metódust, minden paraméterhez konkrét értékeket, úgynevezett argumentumokat biztosít. Az argumentumoknak kompatibilisnek kell lenniük a paramétertípussal, de az argumentum nevének, ha a hívókódban szerepel, nem kell megegyeznie a metódusban definiált paraméterrel. A következő példában a Square metódus egyetlen i nevű intparamétert tartalmaz. Az első metódushívás egy számSquareváltozót ad át a int metódusnak, a másodikat egy numerikus állandót, a harmadikat pedig egy kifejezést.

public static class SquareExample
{
    public static void Main()
    {
        // Call with an int variable.
        int num = 4;
        int productA = Square(num);

        // Call with an integer literal.
        int productB = Square(12);

        // Call with an expression that evaluates to int.
        int productC = Square(productA * 3);
    }

    static int Square(int i)
    {
        // Store input argument in a local variable.
        int input = i;
        return input * input;
    }
}

A metódushívás leggyakoribb formája a pozícióargumentumok; az argumentumokat a metódusparaméterekkel azonos sorrendben szolgáltatja. Ezért az Motorcycle osztály metódusai az alábbi példában leírtak szerint hívhatók meg. A metódus hívása Drive például két argumentumot tartalmaz, amelyek megfelelnek a metódus szintaxisában szereplő két paraméternek. Az első lesz a paraméter értéke miles . A második a paraméter értéke speed lesz.

class TestMotorcycle : Motorcycle
{
    public override double GetTopSpeed() => 108.4;

    static void Main()
    {
        var moto = new TestMotorcycle();

        moto.StartEngine();
        moto.AddGas(15);
        _ = moto.Drive(5, 20);
        double speed = moto.GetTopSpeed();
        Console.WriteLine($"My top speed is {speed}");
    }
}

A metódusok meghívásakor elnevezett argumentumokat is használhat helymeghatározó argumentumok helyett. Névvel ellátott argumentumok használatakor meg kell adnia a paraméter nevét, majd egy kettőspontot (":) és az argumentumot. A metódus argumentumai tetszőleges sorrendben megjelenhetnek, feltéve, hogy az összes szükséges argumentum megtalálható. Az alábbi példa nevesített argumentumokat használ a TestMotorcycle.Drive metódus meghívásához. Ebben a példában a névvel ellátott argumentumok a metódus paraméterlistájából ellenkező sorrendben lesznek átadva.

namespace NamedMotorCycle;

class TestMotorcycle : Motorcycle
{
    public override int Drive(int miles, int speed) =>
        (int)Math.Round((double)miles / speed, 0);

    public override double GetTopSpeed() => 108.4;

    static void Main()
    {
        var moto = new TestMotorcycle();
        moto.StartEngine();
        moto.AddGas(15);
        int travelTime = moto.Drive(speed: 60, miles: 170);
        Console.WriteLine($"Travel time: approx. {travelTime} hours");
    }
}
// The example displays the following output:
//      Travel time: approx. 3 hours

Egy metódust pozicionális argumentumok és nevezett argumentumok használatával is meghívhat. A pozícióargumentumok azonban csak akkor követhetik az elnevezett argumentumokat, ha az elnevezett argumentumok a megfelelő pozícióban vannak. Az alábbi példa egy TestMotorcycle.Drive pozícióargumentum és egy elnevezett argumentum használatával hívja meg az előző példában szereplő metódust.

int travelTime = moto.Drive(170, speed: 55);

Örökölt és felülírt metódusok

A típusban explicit módon definiált tagok mellett egy típus örökli az alaposztályaiban definiált tagokat. Mivel a felügyelt típusrendszer összes típusa közvetlenül vagy közvetve örökli az Object osztályt, minden típus örökli a tagokat, például Equals(Object)a , GetType()és ToString(). Az alábbi példa egy osztályt Person határoz meg, két Person objektumot hoz létre, és meghívja a Person.Equals metódust annak megállapítására, hogy a két objektum egyenlő-e. A Equals metódus azonban nem az Person osztályban van definiálva, hanem a következőtől Objectöröklődik:

public class Person
{
    public string FirstName = default!;
}

public static class ClassTypeExample
{
    public static void Main()
    {
        Person p1 = new() { FirstName = "John" };
        Person p2 = new() { FirstName = "John" };
        Console.WriteLine($"p1 = p2: {p1.Equals(p2)}");
    }
}
// The example displays the following output:
//      p1 = p2: False

A típusok felülbírálhatják az örökölt tagokat a override kulcsszó használatával, és implementációt biztosítanak a felülbírált metódushoz. A metódus aláírásának meg kell egyeznie a felülírt módszerrel. Az alábbi példa az előzőhez hasonló, azzal a kivételt leszámítva, hogy felülbírálja a metódust Equals(Object) . (Felülbírálja a GetHashCode() metódust is, mivel a két módszer konzisztens eredményt ad.)

namespace methods;

public class Person
{
    public string FirstName = default!;

    public override bool Equals(object? obj) =>
        obj is Person p2 &&
        FirstName.Equals(p2.FirstName);

    public override int GetHashCode() => FirstName.GetHashCode();
}

public static class Example
{
    public static void Main()
    {
        Person p1 = new() { FirstName = "John" };
        Person p2 = new() { FirstName = "John" };
        Console.WriteLine($"p1 = p2: {p1.Equals(p2)}");
    }
}
// The example displays the following output:
//      p1 = p2: True

Paraméterek átadása

A C# -beli típusok értéktípusok vagy referenciatípusok. A beépített értéktípusok listáját a Típusok című témakörben találja. Alapértelmezés szerint az értéktípusok és a referenciatípusok is átadódnak érték alapján egy metódusnak.

Paraméterek átadása érték szerint

Amikor érték alapján ad át egy értéktípust egy metódusnak, a rendszer az objektum másolatát továbbítja a metódusnak, és nem magát az objektumot. Ezért a hívott metódus objektumának módosítása nincs hatással az eredeti objektumra, amikor a vezérlő visszatér a hívóhoz.

Az alábbi példa érték szerint ad át egy értéktípust egy metódusnak, az úgynevezett metódus pedig megpróbálja módosítani az értéktípus értékét. Meghatároz egy értéktípusú változót int, inicializálja az értékét 20-ra, és átadja azt egy olyan ModifyValue metódusnak, amely a változó értékét 30-ra módosítja. A metódus visszaadásakor azonban a változó értéke változatlan marad.

public static class ByValueExample
{
    public static void Main()
    {
        var value = 20;
        Console.WriteLine("In Main, value = {0}", value);
        ModifyValue(value);
        Console.WriteLine("Back in Main, value = {0}", value);
    }

    static void ModifyValue(int i)
    {
        i = 30;
        Console.WriteLine("In ModifyValue, parameter value = {0}", i);
        return;
    }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 20

Ha egy hivatkozástípusú objektumot érték alapján ad át egy metódusnak, az objektumra mutató hivatkozást érték adja át. Ez azt jelenti, hogy a metódus nem magát az objektumot kapja meg, hanem egy argumentumot, amely az objektum helyét jelzi. Ha ezzel a hivatkozással módosítja az objektum egy tagját, a változás akkor jelenik meg az objektumban, amikor a vezérlőelem visszatér a hívási metódushoz. A metódusnak átadott objektum cseréje azonban nincs hatással az eredeti objektumra, amikor a vezérlő visszatér a hívóhoz.

Az alábbi példa egy (referenciatípusú) SampleRefTypeosztályt határoz meg. Létrehoz egy SampleRefType objektumot, hozzárendel 44-et a mezőhöz value , és átadja az objektumot a ModifyObject metódusnak. Ez a példa lényegében ugyanazt teszi, mint az előző példában – egy argumentumot érték szerint ad át egy metódusnak. Mivel azonban referenciatípust használ, az eredmény más. A ModifyObject mezőben a obj.value módosítás az argumentum value mezőjét is módosítja, rt, a Main metódusban, 33-ra, ahogy a példa kimenete is mutatja.

public class SampleRefType
{
    public int value;
}

public static class ByRefTypeExample
{
    public static void Main()
    {
        var rt = new SampleRefType { value = 44 };
        ModifyObject(rt);
        Console.WriteLine(rt.value);
    }

    static void ModifyObject(SampleRefType obj) => obj.value = 33;
}

Paraméterek átadása hivatkozás alapján

Egy paramétert hivatkozással ad át, ha módosítani szeretné egy metódus argumentumának értékét, és ezt a változást szeretné tükrözni, amikor a vezérlőelem visszatér a hívási metódushoz. Ha hivatkozás alapján szeretne átadni egy paramétert, használja a kulcsszótref.out Az értékeket hivatkozással is átadhatja, így elkerülheti a másolást, de továbbra is megakadályozhatja a módosításokat a in kulcsszó használatával.

Az alábbi példa megegyezik az előzővel, kivéve, hogy az értéket a ModifyValue metódusra való hivatkozással adjuk át. Ha a paraméter értéke módosul a ModifyValue metódusban, az érték változása akkor jelenik meg, amikor a vezérlő visszatér a hívóhoz.

public static class ByRefExample
{
    public static void Main()
    {
        var value = 20;
        Console.WriteLine("In Main, value = {0}", value);
        ModifyValue(ref value);
        Console.WriteLine("Back in Main, value = {0}", value);
    }

    private static void ModifyValue(ref int i)
    {
        i = 30;
        Console.WriteLine("In ModifyValue, parameter value = {0}", i);
        return;
    }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 30

A ref paraméterekkel gyakran alkalmazott minta a változók értékeinek felcserélése. Két változót ad át egy metódusnak hivatkozás alapján, és a metódus felcseréli a tartalmát. Az alábbi példa egész számértékeket cserél fel.


public static class RefSwapExample
{
    static void Main()
    {
        int i = 2, j = 3;
        Console.WriteLine($"i = {i}  j = {j}");

        Swap(ref i, ref j);

        Console.WriteLine($"i = {i}  j = {j}");
    }

    static void Swap(ref int x, ref int y) =>
        (y, x) = (x, y);
}
// The example displays the following output:
//      i = 2  j = 3
//      i = 3  j = 2

A referencia típusú paraméter átadása lehetővé teszi a hivatkozás értékének módosítását, nem pedig az egyes elemek vagy mezők értékét.

Paramétergyűjtemények

Néha az a követelmény, hogy pontosan hány argumentumot adjon meg a metódushoz, korlátozó. A kulcsszó használatával params jelezheti, hogy egy paraméter paramétergyűjtemény, lehetővé teszi a metódus meghívását változó számú argumentummal. A kulcsszóval params címkézett paraméternek gyűjteménytípusnak kell lennie, és a metódus paraméterlistájának utolsó paraméterének kell lennie.

A hívó ezután négyféleképpen hívhatja meg a metódust a params paraméterrel:

  • A megfelelő típusú gyűjtemény átadásával, amely a kívánt számú elemet tartalmazza. A példa egy gyűjteménykifejezést használ, így a fordító létrehoz egy megfelelő gyűjteménytípust.
  • A megfelelő típusú argumentumok vesszővel tagolt listájának átadásával a metódusnak. A fordító létrehozza a megfelelő gyűjteménytípust.
  • Azáltal, hogy átmegy null.
  • Ha nem ad meg argumentumot a paramétergyűjteménynek.

Az alábbi példa egy olyan metódust GetVowels definiál, amely egy paramétergyűjtemény összes magánhangzóját visszaadja. A Main metódus a metódus meghívásának mind a négy módját szemlélteti. A hívóknak nem kell argumentumokat megadniuk a params módosító paraméterhez. Ebben az esetben a paraméter egy üres gyűjtemény.

static class ParamsExample
{
    static void Main()
    {
        string fromArray = GetVowels(["apple", "banana", "pear"]);
        Console.WriteLine($"Vowels from collection expression: '{fromArray}'");

        string fromMultipleArguments = GetVowels("apple", "banana", "pear");
        Console.WriteLine($"Vowels from multiple arguments: '{fromMultipleArguments}'");

        string fromNull = GetVowels(null);
        Console.WriteLine($"Vowels from null: '{fromNull}'");

        string fromNoValue = GetVowels();
        Console.WriteLine($"Vowels from no value: '{fromNoValue}'");
    }

    static string GetVowels(params IEnumerable<string>? input)
    {
        if (input == null || !input.Any())
        {
            return string.Empty;
        }

        char[] vowels = ['A', 'E', 'I', 'O', 'U'];
        return string.Concat(
            input.SelectMany(
                word => word.Where(letter => vowels.Contains(char.ToUpper(letter)))));
    }
}

// The example displays the following output:
//     Vowels from array: 'aeaaaea'
//     Vowels from multiple arguments: 'aeaaaea'
//     Vowels from null: ''
//     Vowels from no value: ''

A C# 13 előtt a params módosító csak egydimenziós tömbökkel használható.

Választható paraméterek és argumentumok

A metódusdefiníciók megadhatja, hogy a paraméterek szükségesek-e, vagy hogy nem kötelezőek. Alapértelmezés szerint paraméterekre van szükség. A választható paraméterek megadása a paraméter alapértelmezett értékének a metódusdefinícióba való belefogadásával lehetséges. A metódus meghívásakor, ha nem ad meg argumentumot egy választható paraméterhez, a rendszer ehelyett az alapértelmezett értéket használja.

A paraméter alapértelmezett értékét a következő kifejezéstípusok egyikével rendelheti hozzá:

  • Az „állandó” egy típusú érték, például literális karakterlánc vagy szám.

  • Az űrlap default(SomeType)kifejezése, ahol SomeType értéktípus vagy referenciatípus is lehet. Ha referenciatípusról van szó, az gyakorlatilag megegyezik a megadott típussal null. Használhatja a default literálist, mivel a fordító a paraméter deklarációjából következtethet a típusra.

  • Az űrlap new ValType()kifejezése, ahol ValType értéktípus van. Ez a kifejezés meghívja az értéktípus implicit paraméter nélküli konstruktorát, amely nem a típus tényleges tagja.

    Feljegyzés

    Amikor az űrlap egy kifejezése new ValType() meghívja egy értéktípus explicit módon definiált paraméter nélküli konstruktorát, a fordító hibát generál, mivel az alapértelmezett paraméterértéknek fordítási időállandónak kell lennie. Használja a default(ValType) kifejezést vagy a default literált az alapértelmezett paraméterérték megadásához. A paraméter nélküli konstruktorokról további információt a Struktúratípusok cikk Strukturálás inicializálása és alapértelmezett értékei című szakaszában talál.

Ha egy metódus kötelező és nem kötelező paramétereket is tartalmaz, a választható paraméterek a paraméterlista végén lesznek definiálva, az összes kötelező paraméter után.

Az alábbi példa egy metódust határoz meg, ExampleMethodamely egy kötelező és két választható paraméterrel rendelkezik.

public class Options
{
    public void ExampleMethod(int required, int optionalInt = default,
                              string? description = default)
    {
        var msg = $"{description ?? "N/A"}: {required} + {optionalInt} = {required + optionalInt}";
        Console.WriteLine(msg);
    }
}

A hívónak az összes választható paraméterhez meg kell adnia egy argumentumot az utolsó választható paraméterig, amelyhez argumentumot ad meg. ExampleMethod A metódusban például ha a hívó argumentumot ad meg a description paraméterhez, akkor a paraméterhez optionalInt is meg kell adnia egyet. opt.ExampleMethod(2, 2, "Addition of 2 and 2"); érvényes metódushívás; opt.ExampleMethod(2, , "Addition of 2 and 0"); "Argumentum hiányzik" fordítóhibát generál.

Ha egy metódus nevesített argumentumokkal vagy pozíció- és elnevezett argumentumok kombinációjával van meghívva, a hívó kihagyhat minden olyan argumentumot, amely a metódushívás utolsó pozícióargumentumát követi.

Az alábbi példa háromszor hívja meg a ExampleMethod metódust. Az első két metódushívás pozícióargumentumokat használ. Az első kihagyja mindkét választható argumentumot, míg a második kihagyja az utolsó argumentumot. A harmadik metódus meghív egy pozícióargumentumot a szükséges paraméterhez, de egy elnevezett argumentumot használ a description paraméter értékének megadásához, miközben kihagyja az optionalInt argumentumot.

public static class OptionsExample
{
    public static void Main()
    {
        var opt = new Options();
        opt.ExampleMethod(10);
        opt.ExampleMethod(10, 2);
        opt.ExampleMethod(12, description: "Addition with zero:");
    }
}
// The example displays the following output:
//      N/A: 10 + 0 = 10
//      N/A: 10 + 2 = 12
//      Addition with zero:: 12 + 0 = 12

Az opcionális paraméterek használata befolyásolja a túlterhelés feloldását, vagy azt, hogy a C#-fordító hogyan határozza meg, hogy melyik túlterhelést kell meghívni egy metódushíváshoz az alábbiak szerint:

  • A tag egy végrehajtásra jelölt személy, ha minden paramétere név vagy pozíció szerint egyetlen argumentumnak felel meg. Emellett az argumentum átalakítható a paraméter típusára.
  • Ha egynél több jelöltet talál, a rendszer a kifejezetten megadott argumentumokra alkalmazza az előnyben részesített konverziók túlterhelés-feloldási szabályait. Az opcionális paraméterek kihagyott argumentumai figyelmen kívül lesznek hagyva.
  • Ha két jelöltet egyformán jónak ítélnek, előnyben részesítik azokat a jelölteket, akik nem rendelkeznek olyan választható paraméterekkel, amelyek argumentumait kihagyták a hívásban.

Visszaadott értékek

A metódusok visszaadhatnak egy értéket a hívónak. Ha a visszatérési típus (a metódus neve előtt felsorolt típus) nem void, a metódus a kulcsszó használatával visszaadhatja az return értéket. A kulcsszót tartalmazó return utasítás, amelyet egy változó, állandó vagy kifejezés követ, amely megfelel a visszatérési típusnak, visszaadja az értéket a metódushívónak. A nem üres visszatérési típusú metódusoknak a return kulcsszót kell használniuk egy érték visszaadásához. A return kulcsszó a metódus végrehajtását is leállítja.

Ha a visszatérési típus az void, return akkor az érték nélküli utasítás továbbra is hasznos a metódus végrehajtásának leállításához. A return kulcsszó nélkül a metódus leáll, amikor eléri a kódblokk végét.

Ez a két módszer például a return kulcsszót használja egész számok visszaadására:

class SimpleMath
{
    public int AddTwoNumbers(int number1, int number2) =>
        number1 + number2;

    public int SquareANumber(int number) =>
        number * number;
}

A fenti példák kifejezés-törzs tagok. A kifejezésalapú tagok az általuk kiértékelt kifejezés értékét adják vissza.

A metódusokat egy utasítás törzsével és egy return utasítással is definiálhatja:

class SimpleMathExtension
{
    public int DivideTwoNumbers(int number1, int number2)
    {
        return number1 / number2;
    }
}

Metódusból visszaadott érték használatához hozzárendelheti a visszatérési értéket egy változóhoz:

int result = obj.DivideTwoNumbers(6,2);
// The result is 3.
Console.WriteLine(result);

A hívó metódus bárhol használhatja magát a metódushívást, ahol egy azonos típusú érték elegendő lenne. A következő két példakód például ugyanazt a célt valósítja meg:

int result = obj.AddTwoNumbers(1, 2);
result = obj.SquareANumber(result);
// The result is 9.
Console.WriteLine(result);
result = obj.SquareANumber(obj.AddTwoNumbers(1, 2));
// The result is 9.
Console.WriteLine(result);

Néha azt szeretné, hogy a metódus több értéket adjon vissza, mint egyetlen értéket. Több érték visszaadásához használjon tupla típusokat és tupla literálokat. A rekordtípus határozza meg a rekord elemeinek adattípusait. A tuple literálok a visszaadott tupel tényleges értékeit adják meg. Az alábbi példában a (string, string, string, int) meghatározza a GetPersonalInfo metódus által visszaadott tömb típusát. A kifejezés (per.FirstName, per.MiddleName, per.LastName, per.Age) a tupiliterál; a metódus egy PersonInfo objektum korát, valamint az első, középső és családi nevét adja vissza.

public (string, string, string, int) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

A hívó ezután az alábbi kóddal használhatja a visszaadott tömböt:

var person = GetPersonalInfo("111111111");
Console.WriteLine($"{person.Item1} {person.Item3}: age = {person.Item4}");

A tömb típusdefinícióban a tömbelemekhez is lehet nevet rendelni. Az alábbi példa a metódus nevesített elemeket használó alternatív verzióját GetPersonalInfo mutatja be:

public (string FName, string MName, string LName, int Age) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

A GetPersonalInfo metódus előző hívása a következőképpen módosítható:

var person = GetPersonalInfo("111111111");
Console.WriteLine($"{person.FName} {person.LName}: age = {person.Age}");

Ha egy metódus paraméterként használ egy tömböt, és módosítja az egyes elemek értékét, a metódusnak nem kell visszaadnia a tömböt. A C# érték szerint adja át az összes referenciatípust, és egy tömbhivatkozás értéke a tömbhöz mutató mutató. Az alábbi példában a values metódusban végrehajtott változások a DoubleValues tömb tartalmán bármely kód számára megfigyelhetőek, amely hivatkozik a tömbre.


public static class ArrayValueExample
{
    static void Main()
    {
        int[] values = [2, 4, 6, 8];
        DoubleValues(values);
        foreach (var value in values)
        {
            Console.Write("{0}  ", value);
        }
    }

    public static void DoubleValues(int[] arr)
    {
        for (var ctr = 0; ctr <= arr.GetUpperBound(0); ctr++)
        {
            arr[ctr] *= 2;
        }
    }
}
// The example displays the following output:
//       4  8  12  16

Kiterjesztési metódusok

Általában kétféleképpen adhat hozzá metódust egy meglévő típushoz:

  • Módosítsa az adott típus forráskódját. A forrás módosítása kompatibilitástörő változást hoz létre, ha bármilyen privát adatmezőt is hozzáad a metódus támogatásához.
  • Definiálja az új metódust egy származtatott osztályban. Más típusok öröklésével, mint például struktúrák és felsorolások, nem lehet metódust hozzáadni. Arra sem használható, hogy metódust "adjon hozzá" egy lezárt osztályhoz.

A bővítménytagok lehetővé teszik, hogy tagokat "vegyen fel" egy meglévő típusba anélkül, hogy módosítaná magát a típust, vagy öröklött típusban implementálaná az új metódust. A bővítménytagnak sem kell ugyanabban a szerelvényben tartózkodnia, mint a kiterjesztett típus. Úgy hívhat meg egy bővítménymetódust, mintha egy adott típus meghatározott tagja lenne.

További információ: Bővítménytagok.

Aszinkron metódusok

Az aszinkron funkcióval explicit visszahívások nélkül hívhat meg aszinkron metódusokat, vagy manuálisan oszthatja fel a kódot több metódusra vagy lambdakifejezésre.

Ha az aszinkron módosítóval jelöl meg egy metódust, használhatja a vár operátort a metódusban. Amikor a vezérlőelem egy kifejezést ér el await az aszinkron metódusban, a vezérlő visszatér a hívóhoz, ha a várt tevékenység még nem fejeződött be, és a kulcsszóval rendelkező await metódus előrehaladása fel van függesztve, amíg a várt tevékenység befejeződik. Ha a feladat befejeződött, a végrehajtás folytatódhat a metódusban.

Feljegyzés

Az aszinkron metódus akkor tér vissza a hívóhoz, ha vagy az első várt objektummal találkozik, amely még nem fejeződött be, vagy az aszinkron metódus végéhez ér, amelyik előbb következik be.

Az aszinkron metódusok visszatérési Task<TResult>típusa általában az , Task, IAsyncEnumerable<T>vagy void. A void visszatérési típus elsősorban eseménykezelők definiálására szolgál, ahol void visszatérési típusra van szükség. A visszaadott void aszinkron metódus nem használható várakoztatásra, és a void-értéket visszaadó metódus hívója nem tudja elkapni a metódus által dobott kivételeket. Az aszinkron metódusok bármilyen feladathoz hasonló visszatérési típussal rendelkezhetnek.

Az alábbi példában DelayAsync egy aszinkron metódus, amely egy egész számot visszaadó visszatérési utasítással rendelkezik. Mivel aszinkron metódus, a metódus deklarációjának visszatérési típusával kell rendelkeznie Task<int>. Mivel a visszatérési típus az Task<int>, a await kifejezés DoSomethingAsync kiértékelése egész számokat eredményez, ahogy az alábbi int result = await delayTask állítás is mutatja.

class Program
{
    static Task Main() => DoSomethingAsync();

    static async Task DoSomethingAsync()
    {
        Task<int> delayTask = DelayAsync();
        int result = await delayTask;

        // The previous two statements may be combined into
        // the following statement.
        //int result = await DelayAsync();

        Console.WriteLine($"Result: {result}");
    }

    static async Task<int> DelayAsync()
    {
        await Task.Delay(100);
        return 5;
    }
}
// Example output:
//   Result: 5

Az aszinkron metódus nem deklarálhat in, ref vagy out paramétereket, de meghívhat ilyen paraméterekkel rendelkező metódusokat.

Az aszinkron metódusokkal kapcsolatos további információkért lásd: Aszinkron programozás async és await használatával és Aszinkron visszatérési típusok.

Kifejezésalapú tagok

Gyakran előfordul, hogy olyan metódusdefiníciók vannak, amelyek egy kifejezés eredményével azonnal visszatérnek, vagy amelyek egyetlen utasítással rendelkeznek a metódus törzseként. Az alábbi szintaxis parancsikonja segítségével definiálhatja az ilyen metódusokat =>:

public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);

Ha a metódus void értéket ad vissza, vagy aszinkron metódus, akkor a metódus törzsének kifejezésként megadott utasításnak kell lennie (ugyanúgy, mint a lambda kifejezések esetében). Az ingatlanok és indexelők esetében ezeknek csak olvashatók kell lenniük, és nem használja az get hozzáférő kulcsszót.

Iterátorok

Az iterátor egyéni iterációt hajt végre egy gyűjteményen, például egy listán vagy tömbön. Az iterátor a hozamvisszautasítással egyenként adja vissza az egyes elemeket. yield return Az utasítás elérésekor az aktuális hely lesz megjegyezve, hogy a hívó lekérhesse a következő elemet a sorozatban.

Az iterátor visszatérési típusa lehet IEnumerable, IEnumerable<T>, IAsyncEnumerable<T>, IEnumeratorvagy IEnumerator<T>.

További információ: Iterators.

Lásd még