Sdílet prostřednictvím


Metody (Průvodce programováním v C#)

Metoda je blok kódu, který obsahuje řadu příkazů. Program způsobí, že příkazy se spustí voláním metody a určením požadovaných argumentů metody. V jazyce C# se každá spuštěná instrukce provádí v kontextu metody.

Metoda Main je vstupním bodem pro každou aplikaci jazyka C# a při spuštění programu je volána modulem CLR (Common Language Runtime). V aplikaci, která používá příkazy nejvyšší úrovně, Main metoda je generována kompilátorem a obsahuje všechny příkazy nejvyšší úrovně.

Poznámka:

Tento článek popisuje pojmenované metody. Informace o anonymních funkcích naleznete v lambda výrazech.

Podpisy metod

Metody jsou deklarovány ve třídě, struktuře nebo rozhraní zadáním úrovně přístupu, například nebo public, volitelných modifikátorů, jako privateabstract je nebo sealed, návratová hodnota, název metody a všechny parametry metody. Tyto části jsou společně podpisem metody.

Důležité

Návratový typ metody není pro účely přetížení součástí signatury metody. Je však součástí signatury metody při určování kompatibility mezi delegátem a metodou, na kterou odkazuje.

Parametry metody jsou uzavřeny v závorkách a jsou odděleny čárkami. Prázdné závorky označují, že metoda nevyžaduje žádné parametry. Tato třída obsahuje čtyři metody:

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 must implement this.
    public abstract double GetTopSpeed();
}

Přístup k metodě

Volání metody u objektu se podobá přístupu k poli. Za název objektu přidejte tečku, název metody a závorky. Argumenty jsou uvedeny v závorkách a jsou oddělené čárkami. Metody Motorcycle třídy lze proto volat jako v následujícím příkladu:

class TestMotorcycle : Motorcycle
{
    public override double GetTopSpeed()
    {
        return 108.4;
    }

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

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

Parametry metody vs. argumenty

Definice metody určuje názvy a typy požadovaných parametrů. Když volající kód zavolá metodu, poskytne konkrétní hodnoty zvané argumenty pro každý parametr. Argumenty musí být kompatibilní s typem parametru, ale název argumentu (pokud existuje) použitý ve volajícím kódu nemusí být stejný jako parametr definovaný v metodě. Například:

public void Caller()
{
    int numA = 4;
    // Call with an int variable.
    int productA = Square(numA);

    int numB = 32;
    // Call with another int variable.
    int productB = Square(numB);

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

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

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

Předávání podle odkazu vs. předávání podle hodnoty

Ve výchozím nastavení platí, že pokud je instance typu hodnoty předána metodě, její kopie se předá místo samotné instance. Změny argumentu proto nemají žádný vliv na původní instanci ve volající metodě. Pokud chcete předat instanci hodnotového typu odkazem, použijte klíčové slovo ref. Další informace naleznete v tématu Předávání parametrů Value-Type.

Pokud je objekt typu odkazu předán metodě, předá se odkaz na objekt. To znamená, že metoda přijímá nikoli samotný objekt, ale argument, který označuje umístění objektu. Pokud změníte člen objektu pomocí této reference, změna se projeví v argumentu ve volající metodě, i když objekt předáte hodnotou.

Typ odkazu vytvoříte pomocí klíčového class slova, jak ukazuje následující příklad:

public class SampleRefType
{
    public int value;
}

Nyní, pokud předáte objekt, který je založen na tomto typu metodě, je předán odkaz na objekt. Následující příklad předá objekt typu SampleRefType metodě ModifyObject:

public static void TestRefType()
{
    SampleRefType rt = new SampleRefType();
    rt.value = 44;
    ModifyObject(rt);
    Console.WriteLine(rt.value);
}

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

Příklad dělá v podstatě stejnou věc jako předchozí příklad v tom, že předává argument podle hodnoty metodě. Vzhledem k tomu, že se používá typ odkazu, je výsledek jiný. Úprava provedená v ModifyObject na poli value parametru, obj, také změní pole value argumentu, rt, v metodě TestRefType. Metoda TestRefType zobrazí jako výstup 33.

Další informace o předávání referenčních typů podle odkazu a podle hodnoty naleznete v tématu Předávání Reference-Type Parametry a odkazové typy.

Návratové hodnoty

Metody mohou vrátit hodnotu volajícímu. Pokud návratový typ (typ uvedený před názvem metody) není void, metoda může vrátit hodnotu pomocí return příkazu. Příkaz s return klíčovým slovem následovaným hodnotou, která odpovídá návratovém typu, vrátí danou hodnotu volajícímu metody.

Hodnotu lze vrátit volajícímu předáním hodnoty nebo předáním odkazu. Hodnoty se volajícímu vrátí pomocí odkazu, je-li použito klíčové slovo ref v podpisu metody a následuje po každém return klíčovém slovu. Například následující podpis metody a návratový příkaz indikují, že metoda vrací proměnnou pojmenovanou estDistance odkazem na volajícího.

public ref double GetEstimatedDistance()
{
    return ref estDistance;
}

Klíčové return slovo také zastaví provádění metody. Pokud je návratový typ void, příkaz return bez hodnoty je stále užitečný k zastavení provádění metody. Bez klíčového return slova metoda přestane provádět, když dosáhne konce bloku kódu. Metody s návratovým typem, který není void, musí vrátit hodnotu pomocí klíčového slova return. Například tyto dvě metody používají return klíčové slovo k vrácení celých čísel:

class SimpleMath
{
    public int AddTwoNumbers(int number1, int number2)
    {
        return number1 + number2;
    }

    public int SquareANumber(int number)
    {
        return number * number;
    }
}

Pokud chcete použít hodnotu vrácenou metodou, může volající metoda použít samotné volání kdekoli, kde by byla dostatečná hodnota stejného typu. Návratovou hodnotu můžete také přiřadit proměnné. Například následující dva příklady kódu plní stejný účel.

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);

Použití místní proměnné, v tomto případě result, k uložení hodnoty je volitelné. Může pomoct čitelnost kódu nebo může být nutné, pokud potřebujete uložit původní hodnotu argumentu pro celý rozsah metody.

Chcete-li použít hodnotu vrácenou odkazem z metody, je nutné deklarovat místní proměnnou odkaz , pokud chcete upravit její hodnotu. Například pokud metoda Planet.GetEstimatedDistance vrátí Double hodnotu jako odkaz, můžete ji definovat jako místní proměnnou pomocí ref pomocí kódu jako následujícího:

ref double distance = ref Planet.GetEstimatedDistance();

Vrácení multidimenzionálního pole z metody, Mkterá upravuje obsah pole není nutné, pokud volající funkce předala pole do M. Výsledné pole můžete vrátit z M kvůli dobrému stylu nebo funkčnímu toku hodnot, ale není to nutné, protože jazyk C# předává všechny referenční typy podle hodnoty a hodnota odkazu na pole je ukazatel na pole. V metodě Mjsou všechny změny obsahu pole pozorovatelné libovolným kódem, který má odkaz na matici, jak je znázorněno v následujícím příkladu:

static void Main(string[] args)
{
    int[,] matrix = new int[2, 2];
    FillMatrix(matrix);
    // matrix is now full of -1
}

public static void FillMatrix(int[,] matrix)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
    {
        for (int j = 0; j < matrix.GetLength(1); j++)
        {
            matrix[i, j] = -1;
        }
    }
}

Asynchronní metody

Pomocí asynchronní funkce můžete vyvolat asynchronní metody bez použití explicitních zpětných volání nebo ručního rozdělení kódu mezi více metod nebo výrazů lambda.

Pokud metodu označíte modifikátorem async , můžete v metodě použít operátor await . Když ovládací prvek dosáhne výrazu await v asynchronní metodě, ovládací prvek se vrátí volajícímu a průběh v metodě se pozastaví, dokud nebude dokončena očekávaná úloha. Po dokončení úlohy může provádění v metodě pokračovat.

Poznámka:

Asynchronní metoda se vrátí volajícímu, když narazí buď na první čekaný objekt, který ještě není dokončený, nebo se dostane na konec asynchronní metody, podle toho, co nastane dříve.

Asynchronní metoda má obvykle návratový typ Task<TResult>, Task, IAsyncEnumerable<T> nebo void. Návratový void typ se používá především k definování obslužných rutin událostí, kde je vyžadován návratový void typ. Asynchronní metoda, která vrací void , nelze očekávat a volající metody void-returning nemůže zachytit výjimky, které metoda vyvolá. Asynchronní metoda může mít libovolný návratový typ podobný úkolu.

V následujícím příkladu je DelayAsync asynchronní metoda, která má návratový typ Task<TResult>. DelayAsync return obsahuje příkaz, který vrací celé číslo. Proto deklarace DelayAsync metody musí mít návratový Task<int>typ . Vzhledem k tomu, že návratový typ je Task<int>, vyhodnocení výrazu await v DoSomethingAsync vytvoří celé číslo, jak ukazuje následující příkaz: int result = await delayTask.

Metoda Main je příkladem asynchronní metody, která má návratový Tasktyp . Jde do DoSomethingAsync metody a protože je vyjádřena jedním řádkem, může vynechat async a await klíčová slova. Vzhledem k tomu, že DoSomethingAsync je asynchronní metoda, musí být úloha pro volání DoSomethingAsync očekávána, jak ukazuje následující příkaz: await DoSomethingAsync();.

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

Asynchronní metoda nemůže deklarovat žádné parametry ref nebo out , ale může volat metody, které mají tyto parametry.

Další informace o asynchronních metodách naleznete v tématu Asynchronní programování s async a await a Asynchronní návratové typy.

Definice výrazového těla

Je běžné mít definice metod, které se okamžitě vracejí s výsledkem výrazu, nebo které mají jako tělo metody jediný příkaz. Existuje zkratka syntaxe pro definování takových metod pomocí =>:

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);

Pokud metoda vrací void nebo je asynchronní metoda, pak tělo metody musí být výraz příkazu (stejný jako u lambdas). U vlastností a indexerů musí být jen pro čtení a klíčové slovo přistupujícího objektu get nepoužíváte.

Iterátory

Iterátor provádí specifickou iteraci přes kolekci, například seznam nebo pole. Iterátor používá příkaz yield return k vrácení každého prvku vždy po druhém. Když je dosaženo yield return příkazu, aktuální umístění v kódu se zapamatuje. Při příštím volání iterátoru se spuštění znovu zahájí z daného místa.

Iterátor z klientského kódu zavoláte pomocí příkazu foreach .

Návratový typ iterátoru může být IEnumerable, IEnumerable<T>, IAsyncEnumerable<T>, IEnumerator, nebo IEnumerator<T>.

Další informace najdete v tématu Iterátory.

Specifikace jazyka C#

Další informace najdete ve specifikaci jazyka C#. Specifikace jazyka je konečným zdrojem syntaxe a použití jazyka C#.

Viz také