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 tématu Výrazy lambda.

Podpisy metody

Metody jsou deklarovány ve třídě, struktuře nebo rozhraní zadáním úrovně přístupu, například public nebo private, volitelných modifikátorů, jako abstract 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í součástí podpisu metody pro účely přetížení metody. Je však součástí podpisu 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 {0}", speed);
    }
}

Parametry metody vs. argumenty

Definice metody určuje názvy a typy požadovaných parametrů. Při volání kódu volá metodu, poskytuje konkrétní hodnoty volané 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ě. Pří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 typu hodnoty odkazem, použijte ref klíčové slovo. Další informace naleznete v tématu Předávání parametrů typu hodnota.

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í tohoto odkazu, změna se projeví v argumentu ve volající metodě, i když předáte objekt podle hodnoty.

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ý. Změny provedené v ModifyObjectvalue poli parametru , objtaké změní value pole argumentu , rtv TestRefType metodě. 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í parametrů typu reference a typů odkazů.

Vrácené 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 podle hodnoty nebo odkazu. Hodnoty se volajícímu vrátí pomocí odkazu, pokud ref je klíčové slovo použito v podpisu metody a řídí se jednotlivými return klíčovými slovy. 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 voidnávratový typ , return příkaz 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 bez void jsou nutné k vrácení hodnoty pomocí klíčového return slova. 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 dosáhne stejného cíle:

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. Pokud například Planet.GetEstimatedDistance metoda vrátí Double hodnotu podle odkazu, můžete ji definovat jako místní proměnnou odkaz s kódem, jako je následující:

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ýslednou matici můžete vrátit z M dobrého stylu nebo funkčního toku hodnot, ale není to nutné, protože jazyk C# předává všechny odkazové typy podle hodnoty a hodnota odkazu na matici je ukazatel na matici. 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ž dojde buď k prvnímu očekávanému objektu, 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ý Task<TResult>typ , TaskIAsyncEnumerable<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 asynchronní metoda, DelayAsync která má návratový Task<TResult>typ . DelayAsyncreturn 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 DoSomethingAsync , že je asynchronní metoda, musí být úloha volání, která má DoSomethingAsync být 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 asynchronní a await a asynchronní návratové typy.

Definice textu výrazu

Definice metody, které se jednoduše vrátí okamžitě s výsledkem výrazu nebo které mají jeden příkaz jako tělo metody, je běžné. Existuje zástupce 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í vlastní iteraci v 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. yield return Po dosažení příkazu se aktuální umístění v kódu zapamatuje. Při příštím volání iterátoru se z daného umístění restartuje spuštění.

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 v tématu Specifikace jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.

Viz také