Udostępnij za pomocą


Metody (Przewodnik programowania w języku C#)

Metoda to blok kodu, który zawiera serię instrukcji. Program powoduje wykonanie instrukcji przez wywołanie metody i określenie wszelkich wymaganych argumentów metody. W języku C# każda wykonywana instrukcja jest wykonywana w kontekście metody.

Metoda Main jest punktem wejścia dla każdej aplikacji języka C# i jest wywoływana przez środowisko uruchomieniowe języka wspólnego (CLR) po uruchomieniu programu. W aplikacji korzystającej z instrukcji najwyższego poziomu, Main metoda jest generowana przez kompilator i zawiera wszystkie instrukcje najwyższego poziomu.

Uwaga

W tym artykule omówiono metody nazwane. Aby uzyskać informacje o funkcjach anonimowych, zobacz Wyrażenia lambda.

Podpisy metod

Metody są deklarowane w klasie, strukturze lub interfejsie, określając poziom dostępu, taki jak public lub private, opcjonalne modyfikatory, takie jak abstract lub sealed, wartość zwracaną, nazwę metody i dowolne parametry metody. Razem te części stanowią podpis metody.

Ważne

Zwracany typ metody nie jest częścią sygnatury metody dla celów przeciążenia metody. Jednak jest częścią sygnatury metody podczas określania zgodności między delegatem a metodą, na którą wskazuje.

Parametry metody są ujęte w nawiasy i są oddzielone przecinkami. Puste nawiasy wskazują, że metoda nie wymaga żadnych parametrów. Ta klasa zawiera cztery 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();
}

Dostęp do metody

Wywoływanie metody w obiekcie przypomina uzyskiwanie dostępu do pola. Po nazwie obiektu dodaj kropkę, nazwę metody i nawiasy. Argumenty są wyświetlane w nawiasach i są rozdzielane przecinkami. Metody Motorcycle klasy można zatem wywołać tak, jak w poniższym przykładzie:

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 a argumenty

Definicja metody określa nazwy i typy wszystkich wymaganych parametrów. Kiedy kod wywołuje metodę, dostarcza konkretne wartości nazywane argumentami dla każdego parametru. Argumenty muszą być zgodne z typem parametru, ale nazwa argumentu (jeśli istnieje) używana w kodzie wywołującym nie musi być taka sama jak parametr o nazwie zdefiniowanej w metodzie. Na przykład:

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

Przekazywanie przez odwołanie a przekazywanie według wartości

Domyślnie, gdy wystąpienie typu wartości jest przekazywane do metody, jego kopia jest przekazywana zamiast samego wystąpienia. W związku z tym zmiany argumentu nie mają wpływu na oryginalny obiekt w metodzie wywołującej. Aby przekazać wystąpienie typu wartości według odwołania, użyj słowa kluczowego ref . Aby uzyskać więcej informacji, zobacz Przekazywanie parametrów Value-Type.

Gdy obiekt typu odwołania jest przekazywany do metody, przekazywane jest odwołanie do obiektu. Oznacza to, że metoda nie odbiera samego obiektu, ale argument wskazujący lokalizację obiektu. Jeśli zmienisz składnik obiektu przy użyciu tej referencji, zmiana zostanie odzwierciedlona w argumencie metody wywołującej, nawet jeśli przekażesz obiekt według wartości.

Typ odwołania można utworzyć przy użyciu słowa kluczowego class , jak pokazano w poniższym przykładzie:

public class SampleRefType
{
    public int value;
}

Teraz, jeśli przekażesz obiekt oparty na tym typie do metody, zostanie przekazane odwołanie do obiektu. Poniższy przykład przekazuje obiekt typu SampleRefType do metody 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;
}

W przykładzie zasadniczo jest to samo, co w poprzednim przykładzie, ponieważ przekazuje argument przez wartość do metody. Jednakże ponieważ używany jest typ referencyjny, wynik jest inny. Modyfikacja dokonana w ModifyObject w polu value parametru obj powoduje również zmianę w polu value argumentu rt w metodzie TestRefType. Metoda TestRefType wyświetla 33 jako dane wyjściowe.

Aby uzyskać więcej informacji na temat przekazywania typów referencyjnych zarówno przez odwołanie, jak i przez wartość, zobacz Przekazywanie parametrów Reference-Type i Typy referencyjne.

Wartości zwracane

Metody mogą zwracać wartość wywołującemu. Jeśli zwracany typ (typ wymieniony przed nazwą metody) nie jest void, metoda może zwrócić wartość przy użyciu return. Instrukcja zawierająca słowo kluczowe return, po którym pojawia się wartość zgodna z typem zwracanym, przekaże tę wartość do wywołującego metodę.

Wartość może być zwrócona wywołującemu przez wartość lub przez odwołanie. Wartości są zwracane do obiektu wywołującego przez odwołanie, jeśli ref słowo kluczowe jest używane w podpisie metody i jest zgodne z każdym return słowem kluczowym. Na przykład, następująca sygnatura metody i instrukcja return wskazują, że metoda zwraca zmienną o nazwie estDistance przez referencję do elementu wywołującego.

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

Słowo return kluczowe zatrzymuje również wykonywanie metody . Jeśli zwracany typ to void, instrukcja return bez wartości jest nadal przydatna do zatrzymania wykonywania metody. Bez słowa kluczowego return metoda przestanie działać, gdy osiągnie koniec bloku kodu. Metody z typem zwracanym innym niż void muszą używać słowa kluczowego return, aby zwrócić wartość. Na przykład te dwie metody używają słowa kluczowego return do zwracania liczb całkowitych:

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

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

Aby użyć wartości zwróconej przez metodę, metoda wywołująca może zastosować wywołanie tej metody wszędzie tam, gdzie wystarczyłaby wartość tego samego typu. Możesz również przypisać wartość zwracaną do zmiennej. Na przykład następujące dwa przykłady kodu osiągają ten sam cel:

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

Użycie zmiennej lokalnej, w tym przypadku , resultdo przechowywania wartości jest opcjonalne. Może to pomóc w czytelności kodu lub może być konieczne, jeśli trzeba przechowywać oryginalną wartość argumentu dla całego zakresu metody.

Aby użyć wartości zwracanej przez odwołanie z metody, należy zadeklarować zmienną lokalną ref , jeśli zamierzasz zmodyfikować jej wartość. Jeśli na przykład Planet.GetEstimatedDistance metoda zwraca Double wartość według odwołania, możesz zdefiniować ją jako zmienną lokalną ref z kodem, tak jak poniżej:

ref double distance = ref Planet.GetEstimatedDistance();

Zwracanie tablicy wielowymiarowej z metody M, która modyfikuje zawartość tablicy, nie jest konieczne, jeśli funkcja wywołująca przekazała tablicę do metody M. Wynikową tablicę można zwrócić z M w celu zachowania dobrego stylu programowania lub zapewnienia płynnego przepływu wartości, ale nie jest to konieczne, ponieważ język C# przekazuje wszystkie typy referencyjne przez wartość, a wartość odwołania do tablicy to wskaźnik do tablicy. W metodzie Mwszelkie zmiany zawartości tablicy można zaobserwować za pomocą dowolnego kodu, który zawiera odwołanie do tablicy, jak pokazano w poniższym przykładzie:

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

Metody asynchroniczne

Za pomocą funkcji asynchronicznej można wywoływać metody asynchroniczne bez użycia jawnych wywołań zwrotnych lub ręcznego dzielenia kodu między wiele metod lub wyrażeń lambda.

Jeśli oznaczysz metodę za pomocą modyfikatora asynchronicznego , możesz użyć operatora await w metodzie . Gdy sterowanie osiągnie wyrażenie await w metodzie asynchronicznej, kontrola jest przekazywana z powrotem do wywołującego, a postęp w metodzie zostaje zawieszony, aż oczekiwane zadanie zostanie zakończone. Po zakończeniu zadania wykonanie może być wznowione w metodzie .

Uwaga

Metoda asynchroniczna powraca do obiektu wywołującego, gdy napotka pierwszy oczekiwany obiekt, który nie został jeszcze ukończony, lub dotrze do końca metody asynchronicznej, w zależności od tego, co nastąpi wcześniej.

Zwykle metoda asynchroniczna ma typ zwracany Task<TResult>, Task, IAsyncEnumerable<T> lub void. Typ zwracany void jest używany głównie do definiowania procedur obsługi zdarzeń, gdzie wymagany jest void. Nie można czekać na metodę asynchroniczną, która zwraca void, a wywołujący metodę zwracającą void nie może przechwytywać wyjątków zgłaszanych przez tę metodę. Metoda asynchroniczna może mieć dowolny typ zwracania podobny do zadania.

W poniższym przykładzie DelayAsync jest metodą asynchroniczną, która ma zwracany typ Task<TResult>. DelayAsync zawiera instrukcję return zwracającą liczbę całkowitą. Deklaracja metody DelayAsync musi mieć typ zwracany Task<int>. Ponieważ zwracany typ to Task<int>, ocena wyrażenia await w DoSomethingAsync zwraca liczbę całkowitą, jak pokazuje poniższa instrukcja: int result = await delayTask.

Metoda Main jest przykładem metody asynchronicznej, która ma zwracany typ Task. Przechodzi do metody DoSomethingAsync i ponieważ jest wyrażona za pomocą pojedynczego wiersza, może pominąć słowa kluczowe async i await. Ponieważ DoSomethingAsync jest metodą asynchroniczną, zadanie wywołania DoSomethingAsync musi być oczekiwane, jak pokazano w następującej instrukcji: 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

Metoda asynchronizuj nie może zadeklarować żadnych parametrów ref ani out , ale może wywoływać metody, które mają takie parametry.

Aby uzyskać więcej informacji na temat metod asynchronicznych, zobacz Programowanie asynchroniczne z async i await oraz Typy zwracane async.

Definicje konstrukcji wyrażeniowych

Często zdarzają się definicje metod, które po prostu natychmiast zwracają wynik wyrażenia lub mają pojedynczą instrukcję jako treść metody. Istnieje skrót składniowy do definiowania takich metod przy użyciu metody =>:

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

Jeśli metoda zwraca void lub jest metodą asynchroniczną, treść metody musi być wyrażeniem instrukcyjnym (takim samym jak w przypadku lambd). W przypadku właściwości i indeksatorów powinny być tylko do odczytu i nie należy używać słowa kluczowego get akcesora.

Iteratory

Iterator wykonuje niestandardowe iterowanie w kolekcji, jak lista lub tablica. Iterator używa instrukcji yield return, aby zwrócić każdy element jeden po drugim. Po osiągnięciu instrukcji yield return zostanie zapamiętana bieżąca lokalizacja w kodzie. Wykonanie jest uruchamiane ponownie z tej lokalizacji, gdy iterator jest wywoływany następnym razem.

Iterator jest wywoływany z kodu klienta przy użyciu instrukcji foreach .

Zwracany typ iteratora może być IEnumerable, IEnumerable<T>, IAsyncEnumerable<T>, IEnumerator lub IEnumerator<T>.

Aby uzyskać więcej informacji, zobacz Iteratory.

Specyfikacja języka C#

Aby uzyskać więcej informacji, zapoznaj się ze specyfikacją języka C#. Specyfikacja języka jest ostatecznym źródłem informacji o składni i użyciu języka C#.

Zobacz też