Delen via


Methoden in C#

Een methode is een codeblok dat een reeks instructies bevat. Een programma zorgt ervoor dat de instructies worden uitgevoerd door de methode aan te roepen en eventuele vereiste methodeargumenten op te geven. In C# wordt elke uitgevoerde instructie uitgevoerd in de context van een methode.

Notitie

In dit artikel worden benoemde methoden besproken. Zie Lambda-expressies voor informatie over anonieme functies.

Methodehandtekeningen

Methoden worden gedeclareerd in een class, recordof struct door het volgende op te geven:

  • Een optioneel toegangsniveau, zoals public of private. De standaardwaarde is private.
  • Optionele modifiers zoals abstract of sealed.
  • De retourwaarde of void als de methode geen heeft.
  • De naam van de methode.
  • Alle methodeparameters. Methodeparameters staan tussen haakjes en worden gescheiden door komma's. Lege haakjes geven aan dat voor de methode geen parameters zijn vereist.

Deze onderdelen vormen samen de methodehandtekening.

Belangrijk

Een retourtype van een methode maakt geen deel uit van de handtekening van de methode voor overbelasting van de methode. Het maakt echter deel uit van de handtekening van de methode bij het bepalen van de compatibiliteit tussen een gemachtigde en de methode waarnaar deze verwijst.

In het volgende voorbeeld wordt een klasse gedefinieerd met de naam Motorcycle die vijf methoden bevat.

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

De Motorcycle klasse bevat een overbelaste methode. Drive Twee methoden hebben dezelfde naam, maar hun parameterlijsten onderscheiden ze.

Methode-aanroep

Methoden kunnen ofwel exemplaar ofwel statisch zijn. U moet een object instantiëren om een exemplaarmethode op dat exemplaar aan te roepen; een instantiemethode werkt op dat exemplaar en de bijbehorende gegevens. U roept een statische methode aan door te verwijzen naar de naam van het type waartoe de methode behoort; statische methoden werken niet op exemplaargegevens. Het aanroepen van een statische methode via een objectinstantie genereert een compilerfout.

Het aanroepen van een methode lijkt op het openen van een veld. Voeg na de objectnaam (als u een exemplaarmethode aanroept) of de typenaam (als u een static methode aanroept), een punt, de naam van de methode en haakjes toe. Argumenten worden tussen haakjes weergegeven en worden gescheiden door komma's.

Met de methodedefinitie worden de namen en typen parameters opgegeven die vereist zijn. Wanneer een aanroeper de methode aanroept, worden voor elke parameter concrete waarden, argumenten genoemd, weergegeven. De argumenten moeten compatibel zijn met het parametertype, maar de argumentnaam, als deze wordt gebruikt in de aanroepende code, hoeft niet hetzelfde te zijn als de parameter die in de methode is gedefinieerd. In het volgende voorbeeld bevat de Square methode één parameter van het type inti. De eerste methodeaanroep geeft de Square methode een variabele van het type intnum door; de tweede, een numerieke constante en de derde, een expressie.

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

De meest voorkomende vorm van methodeaanroepen gebruikte positionele argumenten; het levert argumenten in dezelfde volgorde als methodeparameters. De methoden van de Motorcycle klasse kunnen daarom worden aangeroepen zoals in het volgende voorbeeld. De aanroep van de Drive methode bevat bijvoorbeeld twee argumenten die overeenkomen met de twee parameters in de syntaxis van de methode. De eerste wordt de waarde van de miles parameter. De tweede wordt de waarde van de parameter 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 {speed}");
    }
}

U kunt ook benoemde argumenten gebruiken in plaats van positionele argumenten bij het aanroepen van een methode. Wanneer u benoemde argumenten gebruikt, geeft u de parameternaam op, gevolgd door een dubbele punt (:) en het argument. Argumenten voor de methode kunnen in elke volgorde worden weergegeven, zolang alle vereiste argumenten aanwezig zijn. In het volgende voorbeeld worden benoemde argumenten gebruikt om de TestMotorcycle.Drive methode aan te roepen. In dit voorbeeld worden de benoemde argumenten doorgegeven in de tegenovergestelde volgorde van de parameterlijst van de methode.

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

U kunt een methode aanroepen met zowel positionele argumenten als benoemde argumenten. Positionele argumenten kunnen echter alleen benoemde argumenten volgen wanneer de benoemde argumenten zich in de juiste posities bevinden. In het volgende voorbeeld wordt de TestMotorcycle.Drive methode uit het vorige voorbeeld aangeroepen met behulp van één positioneel argument en één benoemd argument.

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

Overgenomen en overschreven methoden

Naast de leden die expliciet zijn gedefinieerd in een type, neemt een type leden over die zijn gedefinieerd in de basisklassen. Omdat alle typen in het beheerde typesysteem direct of indirect overnemen van de Object klasse, nemen alle typen de leden over, zoals Equals(Object), GetType()en ToString(). In het volgende voorbeeld wordt een Person klasse gedefinieerd, worden twee Person objecten geïnstitueert en wordt de Person.Equals methode aangeroepen om te bepalen of de twee objecten gelijk zijn. De Equals methode is echter niet gedefinieerd in de Person klasse; deze wordt overgenomen van 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: {p1.Equals(p2)}");
    }
}
// The example displays the following output:
//      p1 = p2: False

Typen kunnen geërfde leden overschrijven door het trefwoord override te gebruiken en een implementatie te bieden voor de overschreven methode. De methode-signatuur moet hetzelfde zijn als de overschreven methode. Het volgende voorbeeld lijkt op de vorige, behalve dat de Equals(Object) methode wordt overschreven. (De GetHashCode() methode wordt ook overschreven, omdat de twee methoden consistente resultaten moeten bieden.)

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

Parameters doorgeven

Typen in C# zijn waardetypen of verwijzingstypen. Zie Typen voor een lijst met ingebouwde waardetypen. Standaard worden zowel waardetypen als verwijzingstypen door een methode doorgegeven als waarde.

Parameters overgeven als waarde

Wanneer een waardetype als waarde wordt doorgegeven aan een methode, wordt een kopie van het object, in plaats van het object zelf, doorgegeven aan de methode. Wijzigingen in het object in de aangeroepen methode hebben daarom geen effect op het oorspronkelijke object wanneer het besturingselement terugkeert naar de aanroeper.

In het volgende voorbeeld wordt een waardetype als waarde doorgegeven aan een methode en probeert de opgeroepen methode de waarde van het waardetype te wijzigen. Het definieert een variabele van het type int, een waardetype, initialiseert de waarde ervan naar 20 en geeft deze door aan een methode met de naam ModifyValue die de waarde van de variabele wijzigt in 30. Wanneer de methode echter retourneert, blijft de waarde van de variabele ongewijzigd.

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

Wanneer een object van een verwijzingstype wordt doorgegeven aan een methode op waarde, wordt een verwijzing naar het object doorgegeven door een waarde. Dat wil gezegd, de methode ontvangt niet het object zelf, maar een argument dat de locatie van het object aangeeft. Als u een lid van het object wijzigt met behulp van deze verwijzing, wordt de wijziging doorgevoerd in het object wanneer het besturingselement terugkeert naar de aanroepmethode. Het vervangen van het object dat aan de methode is doorgegeven, heeft echter geen effect op het oorspronkelijke object wanneer het besturingselement terugkeert naar de aanroeper.

In het volgende voorbeeld wordt een klasse (een verwijzingstype) met de naam SampleRefTypegedefinieerd. Er wordt een SampleRefType object geïnstitueert, 44 aan het value veld toegewezen en het object doorgegeven aan de ModifyObject methode. Dit voorbeeld doet in wezen hetzelfde als in het vorige voorbeeld: het geeft een argument per waarde door aan een methode. Maar omdat een verwijzingstype wordt gebruikt, is het resultaat anders. De wijziging die in ModifyObject aan het obj.value-veld wordt aangebracht, wijzigt ook het value-veld van het argument, rt, in de Main-methode naar 33, zoals de uitvoer uit het voorbeeld laat zien.

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

Parameters doorgeven via referentie

U geeft een parameter door aan de hand van een verwijzing wanneer u de waarde van een argument in een methode wilt wijzigen en deze wijziging wilt weergeven wanneer het besturingselement terugkeert naar de aanroepmethode. Als u een parameter per verwijzing wilt doorgeven, gebruikt u het ref of out trefwoord. U kunt ook een waarde doorgeven door te verwijzen om kopiëren te voorkomen, maar nog steeds wijzigingen te voorkomen met behulp van het in trefwoord.

Het volgende voorbeeld is identiek aan de vorige, behalve dat de waarde wordt doorgegeven door verwijzing naar de ModifyValue methode. Wanneer de waarde van de parameter wordt gewijzigd in de ModifyValue methode, wordt de wijziging in waarde weerspiegeld wanneer het besturingselement terugkeert naar de aanroeper.

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

Een gemeenschappelijk patroon dat door refparameters wordt gebruikt, omvat het wisselen van de waarden van variabelen. U geeft twee variabelen door aan een methode op basis van verwijzing en de methode wisselt de inhoud ervan. In het volgende voorbeeld worden gehele getallen gewisseld.


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

        Swap(ref i, ref j);

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

Door een parameter voor het verwijzingstype door te geven, kunt u de waarde van de verwijzing zelf wijzigen in plaats van de waarde van de afzonderlijke elementen of velden.

Parameterverzamelingen

Soms is de vereiste om het exacte aantal argumenten voor uw methode op te geven beperkend. Door het params trefwoord te gebruiken om aan te geven dat een parameter een parameterverzameling is, kunt u de methode aangeroepen met een variabel aantal argumenten. De parameter die is getagd met het params trefwoord, moet een verzamelingstype zijn en moet de laatste parameter in de parameterlijst van de methode zijn.

Een aanroeper kan vervolgens de methode op vier manieren aanroepen voor de params parameter:

  • Door een verzameling van het juiste type door te geven dat het gewenste aantal elementen bevat. In het voorbeeld wordt een verzamelingsexpressie gebruikt, zodat de compiler een geschikt verzamelingstype maakt.
  • Door een door komma's gescheiden lijst met afzonderlijke argumenten van het juiste type door te geven aan de methode. De compiler maakt het juiste verzamelingstype.
  • Door null te geven.
  • Door geen argument op te geven voor de parameterverzameling.

In het volgende voorbeeld wordt een methode gedefinieerd die alle klinkers retourneert uit een parameterverzameling met GetVowels. De Main methode illustreert alle vier de manieren om de methode aan te roepen. Bellers hoeven geen argumenten op te geven voor parameters die de params wijzigingsfunctie bevatten. In dat geval is de parameter een lege verzameling.

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

Voor C# 13 kan de params modifier alleen worden gebruikt met één dimensionale matrix.

Optionele parameters en argumenten

Een methodedefinitie kan opgeven dat de parameters vereist zijn of dat ze optioneel zijn. Standaard zijn parameters vereist. Optionele parameters worden opgegeven door de standaardwaarde van de parameter op te geven in de methodedefinitie. Wanneer de methode wordt aangeroepen en er geen argument wordt opgegeven voor een optionele parameter, wordt in plaats daarvan de standaardwaarde gebruikt.

U wijst de standaardwaarde van de parameter toe met een van de volgende soorten expressies:

  • Een constante, zoals een letterlijke tekenreeks of een getal.

  • Een expressie van het formulier default(SomeType), waarbij SomeType dit een waardetype of een verwijzingstype kan zijn. Als het een verwijzingstype is, is dit in feite hetzelfde als het opgeven null. U kunt de default letterlijke waarde gebruiken, omdat de compiler het type kan afleiden uit de declaratie van de parameter.

  • Een expressie van het formulier new ValType(), waarbij ValType een waardetype is. Met deze expressie wordt de impliciete parameterloze constructor van het waardetype aangeroepen. Dit is geen echt lid van het type.

    Notitie

    Wanneer een expressie van het formulier new ValType() de expliciet gedefinieerde parameterloze constructor van een waardetype aanroept, genereert de compiler een fout als de standaardparameterwaarde een compilatieconstante moet zijn. Gebruik de default(ValType) expressie of de default letterlijke waarde om de standaardparameterwaarde op te geven. Zie de sectie Struct initialisatie en standaardwaarden van het artikel Structuurtypen voor meer informatie over parameterloze constructors.

Als een methode zowel vereiste als optionele parameters bevat, worden optionele parameters aan het einde van de parameterlijst gedefinieerd, na alle vereiste parameters.

In het volgende voorbeeld wordt een methode gedefinieerd met ExampleMethodéén vereiste en twee optionele parameters.

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

De aanroeper moet een argument opgeven voor alle optionele parameters tot de laatste optionele parameter waarvoor een argument wordt opgegeven. Als de aanroeper in de ExampleMethod methode bijvoorbeeld een argument voor de description parameter levert, moet deze er ook een opgeven voor de optionalInt parameter. opt.ExampleMethod(2, 2, "Addition of 2 and 2"); is een geldige methode-aanroep; opt.ExampleMethod(2, , "Addition of 2 and 0"); genereert een compilerfout 'Argument ontbreekt'.

Als een methode wordt aangeroepen met behulp van benoemde argumenten of een combinatie van positionele en benoemde argumenten, kan de aanroeper alle argumenten weglaten die volgen op het laatste positionele argument in de methodeaanroep.

In het volgende voorbeeld wordt de ExampleMethod methode drie keer aangeroepen. Bij de eerste twee methodeaanroepen worden positionele argumenten gebruikt. De eerste weglaat beide optionele argumenten, terwijl de tweede het laatste argument weglaat. De derde methodeaanroep levert een positioneel argument voor de vereiste parameter, maar gebruikt een benoemd argument om een waarde op te geven aan de description parameter terwijl het optionalInt argument wordt weggelaten.

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

Het gebruik van optionele parameters is van invloed op overbelastingsresolutie of de manier waarop de C#-compiler bepaalt welke overbelasting moet worden aangeroepen voor een methode-aanroep, als volgt:

  • Een lid is een kandidaat voor uitvoering als elk van de parameters op naam of op positie overeenkomt met één argument. Bovendien kan dat argument worden geconverteerd naar het type van de parameter.
  • Als er meer dan één kandidaat wordt gevonden, worden overbelastingsoplossingsregels voor voorkeursconversies toegepast op de argumenten die expliciet zijn opgegeven. Weggelaten argumenten voor optionele parameters worden genegeerd.
  • Als twee kandidaten even goed worden beoordeeld, gaat de voorkeur naar een kandidaat die geen optionele parameters heeft waarvoor argumenten zijn weggelaten in de aanroep.

Retourwaarden

Methoden kunnen een waarde retourneren aan de aanroeper. Als het retourtype (het type dat wordt vermeld vóór de naam van de methode) niet voidis, kan de methode de waarde retourneren met behulp van het return trefwoord. Een instructie met het return trefwoord gevolgd door een variabele, constante of expressie die overeenkomt met het retourtype retourneert die waarde aan de aanroeper van de methode. Methoden met een niet-void-retourtype zijn vereist om het return trefwoord te gebruiken om een waarde te retourneren. Het return trefwoord stopt ook de uitvoering van de methode.

Als het retourtype is void, is een return instructie zonder waarde nog steeds nuttig om de uitvoering van de methode te stoppen. Zonder het return trefwoord wordt de methode niet meer uitgevoerd wanneer het einde van het codeblok wordt bereikt.

Met deze twee methoden wordt bijvoorbeeld het return trefwoord gebruikt om gehele getallen te retourneren:

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

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

De voorgaande voorbeelden zijn expressieleden. Expressieleden retourneren de waarde die door de expressie wordt geretourneerd.

U kunt er ook voor kiezen om uw methoden te definiëren met een hoofdtekst van de instructie en een return instructie:

class SimpleMathExtension
{
    public int DivideTwoNumbers(int number1, int number2)
    {
        return number1 / number2;
    }
}

Als u een waarde wilt gebruiken die wordt geretourneerd op basis van een methode, kunt u de retourwaarde toewijzen aan een variabele:

int result = obj.DivideTwoNumbers(6,2);
// The result is 3.
Console.WriteLine(result);

De aanroepmethode kan ook de methode-aanroep zelf gebruiken, overal waar een waarde van hetzelfde type voldoende zou zijn. De volgende twee codevoorbeelden bereiken bijvoorbeeld hetzelfde doel:

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

Soms wilt u dat uw methode meer dan één waarde retourneert. U gebruikt tuple-typen en tuple-letterlijke waarden om meerdere waarden te retourneren. Het tuple-type definieert de gegevenstypen van de tuple-elementen. Tuple-literals geven de werkelijke waarden van de geretourneerde tuple. In het volgende voorbeeld (string, string, string, int) definieert u het tuple-type dat door de GetPersonalInfo methode wordt geretourneerd. De expressie (per.FirstName, per.MiddleName, per.LastName, per.Age) is de tuple-literal; de methode retourneert de eerste, tweede en familienaam, samen met de leeftijd, van een PersonInfo object.

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

De aanroeper kan vervolgens de teruggegeven tuple gebruiken met behulp van de volgende code:

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

Namen kunnen ook aan de tuple-elementen worden toegewezen in de definitie van het tuple-type. In het volgende voorbeeld ziet u een alternatieve versie van de GetPersonalInfo methode die gebruikmaakt van benoemde elementen:

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

De vorige aanroep van de GetPersonalInfo methode kan vervolgens als volgt worden gewijzigd:

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

Als een methode een matrix als parameter gebruikt en de waarde van afzonderlijke elementen wijzigt, is het niet nodig dat de methode de matrix retourneert. C# geeft alle verwijzingstypen op waarde door en de waarde van een matrixreferentie is de aanwijzer naar de matrix. In het volgende voorbeeld zijn wijzigingen in de inhoud van de values matrix die in de DoubleValues methode zijn aangebracht, waarneembaar door code die een verwijzing naar de matrix bevat.


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

Extensiemethoden

Normaal gesproken zijn er twee manieren om een methode toe te voegen aan een bestaand type:

  • Wijzig de broncode voor dat type. Als u de bron wijzigt, wordt er een belangrijke wijziging gemaakt als u ook persoonlijke gegevensvelden toevoegt om de methode te ondersteunen.
  • Definieer de nieuwe methode in een afgeleide klasse. Een methode kan niet op deze manier worden toegevoegd met behulp van overname voor andere typen, zoals structuren en opsommingen. Het kan ook niet worden gebruikt om een methode toe te voegen aan een verzegelde klasse.

Met extensieleden kunt u leden toevoegen aan een bestaand type zonder het type zelf te wijzigen of de nieuwe methode in een overgenomen type te implementeren. Het uitbreidingslid hoeft zich ook niet in dezelfde assembly te bevinden als het type dat het uitbreidt. U roept een extensiemethode aan alsof het een gedefinieerd lid van een type is.

Zie Extensieleden voor meer informatie.

Asynchrone methoden

Met behulp van de asynchrone functie kunt u asynchrone methoden aanroepen zonder expliciete callbacks te gebruiken of uw code handmatig te splitsen over meerdere methoden of lambda-expressies.

Als u een methode markeert met de asynchrone wijziging, kunt u de wachtoperator in de methode gebruiken. Wanneer het besturingselement een await expressie in de asynchrone methode bereikt, keert het besturingselement terug naar de aanroeper als de wachtende taak niet is voltooid en wordt de voortgang in de methode met het await trefwoord opgeschort totdat de wachtende taak is voltooid. Wanneer de taak is voltooid, kan de uitvoering worden hervat in de methode.

Notitie

Een asynchrone methode keert terug naar de aanroeper wanneer het het eerste wachtende object tegenkomt dat nog niet is voltooid of het einde van de asynchrone methode bereikt, afhankelijk van wat zich het eerst voordoet.

Een asynchrone methode heeft meestal een retourtype Task<TResult>, Taskof IAsyncEnumerable<T>void. Het void retourtype wordt voornamelijk gebruikt om gebeurtenis-handlers te definiëren, waarbij een void retourtype vereist is. Een asynchrone methode die void retourneert kan niet worden afgewacht, en de aanroeper van een methode die geen waarde retourneert kan geen uitzonderingen opvangen die de methode opwerpt. Een asynchrone methode kan elk taakachtig retourtype hebben.

In het volgende voorbeeld DelayAsync is een asynchrone methode met een retourinstructie die een geheel getal retourneert. Omdat het een asynchrone methode is, moet de declaratie van de methode een retourtype van Task<int> hebben. Omdat het retourtype is Task<int>, produceert de evaluatie van de await expressie in DoSomethingAsync een geheel getal, zoals de volgende int result = await delayTask instructie laat zien.

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

Een asynchrone methode kan geen in, ref of out parameters declareren, maar kan wel methoden aanroepen die dergelijke parameters hebben.

Zie Asynchrone programmering met asynchroon en wachten en Asynchrone retourtypen voor meer informatie over asynchrone methoden.

Expressie-leden

Het is gebruikelijk om methodedefinities te hebben die direct worden geretourneerd met het resultaat van een expressie of die één instructie hebben als hoofdtekst van de methode. Er is een syntaxissnelkoppeling voor het definiëren van dergelijke methoden met behulp van =>:

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

Als de methode retourneert void of een asynchrone methode is, moet de hoofdtekst van de methode een instructieexpressie zijn (hetzelfde als bij lambdas). Voor eigenschappen en indexers geldt dat ze alleen-lezen moeten zijn en dat u het get trefwoord accessor niet gebruikt.

Iteratoren

Een iterator voert een aangepaste iteratie uit voor een verzameling, zoals een lijst of een matrix. Een iterator gebruikt de yield return-instructie om elk element afzonderlijk te retourneren. Wanneer een yield return instructie wordt bereikt, wordt de huidige locatie onthouden, zodat de aanroeper het volgende element in de reeks kan opvragen.

Het retourtype van een iterator kan zijnIEnumerable, of IEnumerable<T>IAsyncEnumerable<T>IEnumeratorIEnumerator<T>.

Zie Iterators voor meer informatie.

Zie ook