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 onderwerp 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 vijf methoden:

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 worden onderscheiden door hun parametertypen.

Methode-aanroep

Methoden kunnen exemplaar of 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. Als u een statische methode probeert aan te roepen via een objectexemplaren, wordt er een compilerfout gegenereerd.

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 int i. De eerste methodeaanroep geeft de Square methode een variabele van het type int num 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 speed parameter.

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

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

Typen kunnen overgenomen leden overschrijven met behulp van het override trefwoord en een implementatie bieden voor de overschreven methode. De methodehandtekening moet hetzelfde zijn als de overschreven methode. Het volgende voorbeeld lijkt op de vorige, behalve dat de Equals(Object) methode wordt overschreven. (De methode wordt ook overschreven GetHashCode() , omdat de twee methoden zijn bedoeld om consistente resultaten te 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: {0}", 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 doorgegeven aan een methode.

Parameters doorgeven op waarde

Wanneer een waardetype wordt doorgegeven aan een methode op waarde, 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 doorgegeven aan een methode op waarde en de aangeroepen methode probeert 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 het obj.value veld wordt aangebracht, wijzigt ook het value veld van het argument, rtin de Main methode in 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 per verwijzing

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 = {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

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 die u opgeeft het exacte aantal argumenten voor uw methode 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 door te geven null.
  • Door geen argument op te geven voor de parameterverzameling.

In het volgende voorbeeld wordt een methode gedefinieerd die GetVowels alle klinkers uit een parameterverzameling retourneert. 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 in C# 10 en hoger 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 methode, indexeerfunctie of constructor is een kandidaat voor uitvoering als elk van de parameters overeenkomt met de naam of op positie van één argument en dat argument kan 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 bovenstaande 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 SimpleMathExtnsion
{
    public int DivideTwoNumbers(int number1, int number2)
    {
        return number1 / number2;
    }
}

Als u een waarde wilt gebruiken die wordt geretourneerd door een methode, kan de aanroepende methode overal een waarde van hetzelfde type gebruiken. U kunt de retourwaarde ook toewijzen aan een variabele. De volgende drie 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);
result = obj2.DivideTwoNumbers(6,2);
// The result is 3.
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. Letterlijke waarden van tuple bieden 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 letterlijke tuple. De methode retourneert de eerste, middelste 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 geretourneerde tuple gebruiken met behulp van de volgende code:

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

Namen kunnen ook worden toegewezen aan de tuple-elementen 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 extensiemethoden kunt u een methode toevoegen aan een bestaand type zonder het type zelf te wijzigen of de nieuwe methode in een overgenomen type te implementeren. De extensiemethode 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 Extensiemethoden 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 retourneert void , kan niet worden gewacht en de aanroeper van een methode voor het retourneren van ongeldige gegevens kan geen uitzonderingen vangen die de methode genereert. 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 Task<int>de methode een retourtype 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 parameters in, verw of out declareren, maar kan methoden aanroepen die dergelijke parameters hebben.

Zie Asynchrone programmering met asynchrone asynchrone typen en wachten en Asynchroon retourneren voor meer informatie over asynchrone methoden.

Expressie-bodyied 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 indexeerfuncties moeten ze alleen-lezen zijn en u gebruikt het get trefwoord accessor niet.

Iterators

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

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

Zie Iterators voor meer informatie.

Zie ook