Metoder i C#

En metod är ett kodblock som innehåller en serie instruktioner. Ett program gör att uttrycken körs genom att anropa metoden och ange eventuella obligatoriska metodargument. I C# utförs varje körd instruktion i kontexten för en metod. Metoden Main är startpunkten för varje C#-program och anropas av CLR (Common Language Runtime) när programmet startas.

Kommentar

I det här avsnittet beskrivs namngivna metoder. Information om anonyma funktioner finns i Lambda-uttryck.

Metodsignaturer

Metoderna deklareras i en class, record, eller struct genom att ange:

  • En valfri åtkomstnivå, till exempel public eller private. Standardvärdet är private.
  • Valfria modifierare som abstract eller sealed.
  • Returvärdet, eller void om metoden inte har någon.
  • Metodnamnet.
  • Alla metodparametrar. Metodparametrar omges av parenteser och avgränsas med kommatecken. Tomma parenteser anger att metoden inte kräver några parametrar.

Dessa delar utgör tillsammans metodsignaturen.

Viktigt!

En returtyp för en metod ingår inte i metodens signatur för metodöverlagring. Det är dock en del av signaturen för metoden när du fastställer kompatibiliteten mellan ett ombud och den metod som den pekar på.

I följande exempel definieras en klass med namnet Motorcycle som innehåller fem metoder:

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

Klassen Motorcycle innehåller en överbelastad metod, Drive. Två metoder har samma namn, men måste särskiljas av deras parametertyper.

Metodanrop

Metoderna kan vara antingen instanser eller statiska. Om du anropar en instansmetod måste du instansiera ett objekt och anropa metoden för objektet. en instansmetod fungerar på den instansen och dess data. Du anropar en statisk metod genom att referera till namnet på den typ som metoden tillhör. statiska metoder fungerar inte på instansdata. Försök att anropa en statisk metod via en objektinstans genererar ett kompilatorfel.

Att anropa en metod är som att komma åt ett fält. Efter objektnamnet (om du anropar en instansmetod) eller typnamnet (om du anropar en static metod) lägger du till en punkt, namnet på metoden och parenteser. Argument visas inom parenteserna och avgränsas med kommatecken.

Metoddefinitionen anger namn och typer av parametrar som krävs. När en anropare anropar metoden innehåller den konkreta värden, som kallas argument, för varje parameter. Argumenten måste vara kompatibla med parametertypen, men argumentnamnet, om det används i den anropande koden, behöver inte vara samma som parametern med namnet som definierats i metoden. I följande exempel Square innehåller metoden en enda parameter av typen int med namnet i. Det första metodanropet Square skickar metoden en variabel av typen int med namnet num; den andra, en numerisk konstant och den tredje, ett uttryck.

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

Den vanligaste formen av metodanrop använde positionsargument. den tillhandahåller argument i samma ordning som metodparametrar. Metoderna för Motorcycle klassen kan därför anropas som i följande exempel. Anropet Drive till metoden innehåller till exempel två argument som motsvarar de två parametrarna i metodens syntax. Den första blir värdet för parametern miles , det andra värdet för parametern speed .

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 {0}", speed);
    }
}

Du kan också använda namngivna argument i stället för positionella argument när du anropar en metod. När du använder namngivna argument anger du parameternamnet följt av ett kolon (":") och argumentet. Argument till metoden kan visas i valfri ordning, så länge alla nödvändiga argument finns. I följande exempel används namngivna argument för att anropa TestMotorcycle.Drive metoden. I det här exemplet skickas de namngivna argumenten i motsatt ordning från metodens parameterlista.

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(miles: 170, speed: 60);
        Console.WriteLine("Travel time: approx. {0} hours", travelTime);
    }
}
// The example displays the following output:
//      Travel time: approx. 3 hours

Du kan anropa en metod med både positionella argument och namngivna argument. Positionella argument kan dock bara följa namngivna argument när de namngivna argumenten är i rätt positioner. I följande exempel anropas TestMotorcycle.Drive metoden från föregående exempel med hjälp av ett positionsargument och ett namngivet argument.

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

Ärvda och åsidosatta metoder

Förutom de medlemmar som uttryckligen definieras i en typ ärver en typ medlemmar som definierats i dess basklasser. Eftersom alla typer i det hanterade typsystemet ärver direkt eller indirekt från Object klassen ärver alla typer dess medlemmar, till exempel Equals(Object), GetType()och ToString(). I följande exempel definieras en Person klass, två Person objekt instansieras och metoden anropas Person.Equals för att avgöra om de två objekten är lika. Metoden definieras dock inte i Person klassen. Den Equals ärvs från Object.

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: {0}", p1.Equals(p2));
    }
}
// The example displays the following output:
//      p1 = p2: False

Typer kan åsidosätta ärvda medlemmar med hjälp av nyckelordet override och tillhandahålla en implementering för den åsidosatta metoden. Metodsignaturen måste vara samma som för den åsidosatta metoden. Följande exempel liknar det föregående, förutom att det åsidosätter Equals(Object) metoden. (Metoden åsidosätts GetHashCode() också eftersom de två metoderna är avsedda att ge konsekventa resultat.)

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: {0}", p1.Equals(p2));
    }
}
// The example displays the following output:
//      p1 = p2: True

Skicka parametrar

Typer i C# är antingen värdetyper eller referenstyper. En lista över inbyggda värdetyper finns i Typer. Som standard skickas både värdetyper och referenstyper till en metod efter värde.

Skicka parametrar efter värde

När en värdetyp skickas till en metod efter värde skickas en kopia av objektet i stället för själva objektet till metoden. Därför har ändringar i objektet i den anropade metoden ingen effekt på det ursprungliga objektet när kontrollen återgår till anroparen.

I följande exempel skickas en värdetyp till en metod efter värde och den anropade metoden försöker ändra värdetypens värde. Den definierar en variabel av typen int, som är en värdetyp, initierar värdet till 20 och skickar den till en metod med namnet ModifyValue som ändrar variabelns värde till 30. När metoden returnerar förblir dock variabelns värde oförändrat.

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

När ett objekt av en referenstyp skickas till en metod efter värde skickas en referens till objektet av värdet. Metoden tar alltså inte emot själva objektet, utan ett argument som anger objektets plats. Om du ändrar en medlem i objektet med hjälp av den här referensen återspeglas ändringen i objektet när kontrollen återgår till anropande metod. Att ersätta objektet som skickades till metoden har dock ingen effekt på det ursprungliga objektet när kontrollen återgår till anroparen.

I följande exempel definieras en klass (som är en referenstyp) med namnet SampleRefType. Det instansierar ett SampleRefType objekt, tilldelar 44 till dess value fält och skickar objektet till ModifyObject -metoden. Det här exemplet gör i stort sett samma sak som i föregående exempel– det skickar ett argument efter värde till en metod. Men eftersom en referenstyp används är resultatet annorlunda. Den ändring som görs i ModifyObjectobj.value fältet ändrar value också argumentets fält, rt, i Main metoden till 33, som utdata från exemplet visar.

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

Skicka parametrar efter referens

Du skickar en parameter efter referens när du vill ändra värdet för ett argument i en metod och vill återspegla den ändringen när kontrollen återgår till anropande metoden. Om du vill skicka en parameter efter referens använder du nyckelordet ref eller out . Du kan också skicka ett värde med referens för att undvika kopiering men ändå förhindra ändringar med hjälp av nyckelordet in .

Följande exempel är identiskt med det föregående, förutom att värdet skickas med referens till ModifyValue metoden. När värdet för parametern ändras i ModifyValue metoden återspeglas värdeändringen när kontrollen återgår till anroparen.

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

Ett vanligt mönster som används av referensparametrar är att växla värdena för variabler. Du skickar två variabler till en metod efter referens, och metoden byter innehåll. I följande exempel växlas heltalsvärden.


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

        Swap(ref i, ref j);

        Console.WriteLine("i = {0}  j = {1}", i, 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

Genom att skicka en referenstypsparameter kan du ändra värdet för själva referensen i stället för värdet för dess enskilda element eller fält.

Parametermatriser

Ibland är kravet på att du anger det exakta antalet argument till din metod restriktivt. Genom att använda nyckelordet params för att ange att en parameter är en parametermatris tillåter du att metoden anropas med ett variabelt antal argument. Parametern som är taggad med nyckelordet params måste vara en matristyp och den måste vara den sista parametern i metodens parameterlista.

En anropare kan sedan anropa metoden på något av fyra sätt:

  • Genom att skicka en matris av lämplig typ som innehåller önskat antal element.
  • Genom att skicka en kommaavgränsad lista över enskilda argument av lämplig typ till metoden.
  • Genom att skicka null.
  • Genom att inte ange ett argument för parametermatrisen.

I följande exempel definieras en metod med namnet GetVowels som returnerar alla vokaler från en parametermatris. Metoden Main illustrerar alla fyra sätten att anropa metoden. Anropare behöver inte ange några argument för parametrar som innehåller params modifieraren. I så fall är parametern en tom matris.

static class ParamsExample
{
    static void Main()
    {
        string fromArray = GetVowels(["apple", "banana", "pear"]);
        Console.WriteLine($"Vowels from array: '{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 string[]? input)
    {
        if (input == null || input.Length == 0)
        {
            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: ''

Valfria parametrar och argument

En metoddefinition kan ange att dess parametrar krävs eller att de är valfria. Som standard krävs parametrar. Valfria parametrar anges genom att inkludera parameterns standardvärde i metoddefinitionen. När metoden anropas används standardvärdet i stället om inget argument anges för en valfri parameter.

Parameterns standardvärde måste tilldelas av någon av följande typer av uttryck:

  • En konstant, till exempel en literalsträng eller ett tal.

  • Ett uttryck för formuläret default(SomeType), där SomeType kan vara antingen en värdetyp eller en referenstyp. Om det är en referenstyp är det i praktiken samma sak som att nullange . Du kan använda literalen default eftersom kompilatorn kan härleda typen från parameterns deklaration.

  • Ett uttryck för formuläret new ValType(), där ValType är en värdetyp. Detta anropar värdetypens implicita parameterlösa konstruktor, som inte är en faktisk medlem av typen.

    Kommentar

    När ett uttryck i formuläret new ValType() anropar den uttryckligen definierade parameterlösa konstruktorn av en värdetyp i C# 10 och senare, genererar kompilatorn ett fel eftersom standardparametervärdet måste vara en kompileringskonstant. default(ValType) Använd uttrycket eller literalen default för att ange standardparametervärdet. Mer information om parameterlösa konstruktorer finns i avsnittet Struct-initiering och standardvärden i artikeln Strukturtyper .

Om en metod innehåller både obligatoriska och valfria parametrar definieras valfria parametrar i slutet av parameterlistan, efter alla obligatoriska parametrar.

I följande exempel definieras en metod, ExampleMethod, som har en obligatorisk och två valfria parametrar.

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

Om en metod med flera valfria argument anropas med positionsargument måste anroparen ange ett argument för alla valfria parametrar från den första till den sista som ett argument anges för. Om anroparen till exempel tillhandahåller ett argument för parametern ExampleMethoddescription måste den också ange ett för parametern optionalInt . opt.ExampleMethod(2, 2, "Addition of 2 and 2"); är ett giltigt metodanrop. opt.ExampleMethod(2, , "Addition of 2 and 0"); genererar kompilatorfelet "Argument saknas".

Om en metod anropas med namngivna argument eller en kombination av positionella och namngivna argument kan anroparen utelämna argument som följer det sista positionsargumentet i metodanropet.

I följande exempel anropas ExampleMethod metoden tre gånger. De två första metodanropen använder positionella argument. Den första utelämnar båda valfria argumenten, medan den andra utelämnar det sista argumentet. Det tredje metodanropet tillhandahåller ett positionsargument för den obligatoriska parametern, men använder ett namngivet argument för att ange ett värde till parametern description samtidigt som argumentet utelämnas optionalInt .

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

Användningen av valfria parametrar påverkar överbelastningsupplösningen eller det sätt på vilket C#-kompilatorn avgör vilken viss överlagring som ska anropas av ett metodanrop enligt följande:

  • En metod, indexerare eller konstruktor är en kandidat för körning om var och en av dess parametrar antingen är valfria eller motsvarar, efter namn eller position, ett enda argument i anropande instruktion, och det argumentet kan konverteras till parametertypen.
  • Om fler än en kandidat hittas tillämpas regler för överbelastningsmatchning för föredragna konverteringar på de argument som uttryckligen anges. Utelämnade argument för valfria parametrar ignoreras.
  • Om två kandidater bedöms vara lika bra går preferensen till en kandidat som inte har valfria parametrar för vilka argument utelämnades i anropet. Detta är en följd av en allmän inställning i överbelastningsmatchning för kandidater som har färre parametrar.

Returvärden

Metoder kan returnera ett värde till anroparen. Om returtypen (den typ som anges före metodnamnet) inte voidär kan metoden returnera värdet med hjälp av nyckelordet return . En instruktion med nyckelordet return följt av en variabel, konstant eller ett uttryck som matchar returtypen returnerar värdet till metodanroparen. Metoder med en icke-void returtyp krävs för att använda nyckelordet return för att returnera ett värde. Nyckelordet return stoppar även körningen av metoden.

Om returtypen är voidär en return instruktion utan värde fortfarande användbar för att stoppa körningen av metoden. Utan nyckelordet return slutar metoden att köras när den når slutet av kodblocket.

Dessa två metoder använder till exempel nyckelordet return för att returnera heltal:

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

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

Om du vill använda ett värde som returneras från en metod kan anropsmetoden använda själva metodanropet var som helst där ett värde av samma typ skulle vara tillräckligt. Du kan också tilldela returvärdet till en variabel. Följande två kodexempel uppnår till exempel samma mål:

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

I det här fallet resultär det valfritt att använda en lokal variabel för att lagra ett värde. Det kan underlätta kodens läsbarhet, eller så kan det vara nödvändigt om du behöver lagra det ursprungliga värdet för argumentet för hela metodens omfång.

Ibland vill du att metoden ska returnera mer än ett enda värde. Du kan enkelt göra detta genom att använda tupplar ochtupplarlitraler. Tuppelns typ definierar datatyperna för tuppelns element. Tuppelns literaler anger de faktiska värdena för den returnerade tuppeln. I följande exempel (string, string, string, int) definierar den tupplartyp som returneras av GetPersonalInfo metoden. Uttrycket (per.FirstName, per.MiddleName, per.LastName, per.Age) är tuppelns literal. Metoden returnerar ett objekts första, mellersta och efternamn, tillsammans med ett objekts PersonInfo ålder.

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

Anroparen kan sedan använda den returnerade tuppeln med kod som följande:

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

Namn kan också tilldelas till tuppelns element i tuppelns typdefinition. I följande exempel visas en alternativ version av GetPersonalInfo metoden som använder namngivna element:

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

Föregående anrop till GetPersonalInfo metoden kan sedan ändras på följande sätt:

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

Om en metod skickas en matris som ett argument och ändrar värdet för enskilda element, är det inte nödvändigt att metoden returnerar matrisen, även om du kan välja att göra det för bra format eller funktionellt flöde av värden. Det beror på att C# skickar alla referenstyper efter värde och värdet för en matrisreferens är pekaren till matrisen. I följande exempel kan ändringar av innehållet i matrisen values som görs i DoubleValues metoden observeras av all kod som har en referens till matrisen.


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

Tilläggsmetoder

Vanligtvis finns det två sätt att lägga till en metod i en befintlig typ:

  • Ändra källkoden för den typen. Du kan naturligtvis inte göra detta om du inte äger typens källkod. Och detta blir en icke-bakåtkompatibel ändring om du även lägger till några privata datafält som stöd för metoden.
  • Definiera den nya metoden i en härledd klass. Det går inte att lägga till en metod på det här sättet med arv för andra typer, till exempel strukturer och uppräkningar. Den kan inte heller användas för att "lägga till" en metod i en förseglad klass.

Med tilläggsmetoder kan du "lägga till" en metod i en befintlig typ utan att ändra själva typen eller implementera den nya metoden i en ärvd typ. Tilläggsmetoden behöver inte heller finnas i samma sammansättning som den typ den utökar. Du anropar en tilläggsmetod som om den vore en definierad medlem av en typ.

Mer information finns i Tilläggsmetoder.

Asynkrona metoder

Genom att använda funktionen async kan du anropa asynkrona metoder utan att använda explicita motringningar eller manuellt dela upp koden mellan flera metoder eller lambda-uttryck.

Om du markerar en metod med asynkron modifierare kan du använda await-operatorn i -metoden. När kontrollen når ett await uttryck i asynkron metod återgår kontrollen till anroparen om den väntade aktiviteten inte har slutförts och förloppet i metoden med nyckelordet await pausas tills den väntade aktiviteten har slutförts. När uppgiften är klar kan körningen återupptas i -metoden.

Kommentar

En asynkron metod återgår till anroparen när den antingen stöter på det första väntande objektet som ännu inte har slutförts eller om den kommer till slutet av async-metoden, beroende på vilket som inträffar först.

En asynkron metod har vanligtvis en returtyp av Task<TResult>, TaskIAsyncEnumerable<T>eller void. Returtypen void används främst för att definiera händelsehanterare, där en void returtyp krävs. Det går inte att vänta på en asynkron metod som returnerar void och anroparen för en void-returning-metod kan inte fånga undantag som metoden genererar. En asynkron metod kan ha valfri typ av aktivitetsliknande retur.

I följande exempel DelayAsync är en asynkron metod som har en retursats som returnerar ett heltal. Eftersom det är en asynkron metod måste dess metoddeklaration ha en returtyp av Task<int>. Eftersom returtypen är Task<int>genererar utvärderingen av await uttrycket i DoSomethingAsync ett heltal, vilket visas i följande int result = await delayTask instruktion.

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

En asynkron metod kan inte deklarera några in-, referens- eller utparametrar, men den kan anropa metoder som har sådana parametrar.

Mer information om asynkrona metoder finns i Asynkron programmering med asynkron programmering med asynkrona och väntande och Async-returtyper.

Medlemmar i uttrycksfyllnad

Det är vanligt att ha metoddefinitioner som helt enkelt returneras omedelbart med resultatet av ett uttryck, eller som har en enda instruktion som brödtext för metoden. Det finns en syntaxgenväg för att definiera sådana metoder med hjälp av =>:

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

Om metoden returnerar void eller är en asynkron metod måste metodens brödtext vara ett uttryck (samma som med lambdas). För egenskaper och indexerare måste de vara skrivskyddade och du använder inte nyckelordet get accessor.

Iteratorer

En iterator utför en anpassad iteration över en samling, till exempel en lista eller en matris. En iterator använder avkastningsreturinstrukturen för att returnera varje element ett i taget. När en yield return instruktion har nåtts sparas den aktuella platsen så att anroparen kan begära nästa element i sekvensen.

Returtypen för en iterator kan vara IEnumerable, IEnumerable<T>, IAsyncEnumerable<T>, IEnumeratoreller IEnumerator<T>.

Mer information finns i Iteratorer.

Se även