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 instrukcjiMain najwyższego poziomu 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, struktury lub interfejsie, określając poziom dostępu, taki jak lub , opcjonalne modyfikatory, takie jak publicabstract lub privatesealed, wartość zwracana, nazwa metody i wszystkie parametry metody. Te części razem są podpisem metody .

Ważne

Zwracany typ metody nie jest częścią podpisu metody do celów przeciążenia metody. Jednak jest ona częścią podpisu metody podczas określania zgodności między delegatem a metodą, do której 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 {0}", speed);
    }
}

Parametry metody a argumenty

Definicja metody określa nazwy i typy wszystkich wymaganych parametrów. Podczas wywoływania kodu wywołuje metodę, udostępnia 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 oryginalne wystąpienie 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 typu wartości.

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 element członkowski obiektu przy użyciu tego odwołania, 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 ponieważ jest używany typ odwołania, wynik jest inny. Modyfikacja wprowadzona w ModifyObjectvalue polu parametru obj, również zmienia value pole argumentu , rtw metodzie TestRefType . Metoda TestRefType wyświetla 33 jako dane wyjściowe.

Aby uzyskać więcej informacji na temat przekazywania typów odwołań według odwołania i wartości, zobacz Przekazywanie parametrów typu odwołania i typów odwołań.

Wartości zwracane

Metody mogą zwracać wartość do elementu wywołującego. Jeśli zwracany typ (typ wymieniony przed nazwą metody) nie voidjest , metoda może zwrócić wartość przy użyciu instrukcjireturn. Instrukcja ze słowem kluczowym, po którym następuje wartość zgodna z return typem zwracanym, zwróci tę wartość do wywołującego metodę.

Wartość może zostać zwrócona do elementu wywołującego według wartości lub odwołania. 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 metoda podpis i instrukcja return wskazują, że metoda zwraca zmienną o nazwie estDistance przy użyciu odwołania 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, return instrukcja 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 bez wartości są wymagane do użycia return słowa kluczowego w celu zwrócenia wartości. 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 z metody, metoda wywołująca może użyć wywołania metody w dowolnym miejscu, w jakim wartość tego samego typu byłaby wystarczająca. 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 Mmetody . Wynikową tablicę można zwrócić dla M dobrego stylu lub funkcjonalnego przepływu wartości, ale nie jest to konieczne, ponieważ język C# przekazuje wszystkie typy odwołań według wartości, a wartość odwołania do tablicy jest wskaźnikiem 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 kontrolka osiągnie wyrażenie await w metodzie asynchronicznej, kontrolka powróci do elementu wywołującego i postęp w metodzie zostanie zawieszony do momentu zakończenia oczekiwanego zadania. Po zakończeniu zadania wykonanie może być wznowione w metodzie .

Uwaga

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

Metoda asynchronicznie zwykle ma zwracany typ Task<TResult>, TaskIAsyncEnumerable<T>lub void. Zwracany void typ jest używany głównie do definiowania procedur obsługi zdarzeń, w których wymagany jest zwracany void typ. Nie można oczekiwać metody asynchronicznej, która zwraca void wartość , a obiekt wywołujący metody zwracanej przez pustkę nie może przechwytywać wyjątków zgłaszanych przez metodę. Metoda asynchronizna może mieć dowolny typ zwracany podobny do zadania.

W poniższym przykładzie jest metodą asynchroniową, DelayAsync która ma zwracany typ Task<TResult>. DelayAsync zawiera instrukcję return zwracającą liczbę całkowitą. W związku z DelayAsync tym deklaracja metody musi mieć typ zwracany Task<int>. Ponieważ zwracany typ to Task<int>, obliczanie await wyrażenia w obiekcie DoSomethingAsync generuje liczbę całkowitą, jak pokazano w poniższej instrukcji: int result = await delayTask.

Metoda Main jest przykładem metody asynchronicznej, która ma zwracany typ Task. Przechodzi do DoSomethingAsync metody i dlatego, że jest wyrażona za pomocą pojedynczego wiersza, może pominąć async słowa kluczowe i await . Ponieważ DoSomethingAsync jest metodą asynchroniową, 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 Asynchroniczne programowanie za pomocą asynchronicznych typów asynchronicznych i await i Async zwracanych typów.

Definicje treści wyrażeń

Często istnieją definicje metod, które po prostu zwracają się natychmiast z wynikiem wyrażenia lub które 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 metodę async lub jest metodą asynchronicznym, treść metody musi być wyrażeniem instrukcji (takim samym jak w przypadku lambd). W przypadku właściwości i indeksatorów muszą być tylko do odczytu i nie należy używać słowa kluczowego get dostępu.

Iteratory

Iterator wykonuje iterację niestandardową w kolekcji, taką jak lista lub tablica. Iterator używa instrukcji zwrotu wydajności, aby zwrócić każdy element jeden naraz. yield return Po osiągnięciu instrukcji 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 mieć IEnumerablewartość , , IAsyncEnumerable<T>IEnumerable<T>, IEnumeratorlub IEnumerator<T>.

Aby uzyskać więcej informacji, zobacz Iteratory.

specyfikacja języka C#

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

Zobacz też