Functies

Wat is een functie?

Een belangrijke bouwsteen van een programma is de functie. Een functie bevat een stuk code dat opgeroepen kan worden in het programma. Werken met functies heeft een aantal voordelen:

  • Dezelfde code kan meerdere malen in een programma gebruikt worden zonder dat ze telkens opnieuw volledig in het programma geplaatst moet worden.
  • Een programma kan beter gestructureerd worden en wordt beter leesbaar.
  • De code is makkelijker aanpasbaar. Indien er een wijziging aan de functie aangebracht wordt, dan zet deze wijziging zich automatisch door naar alle plaatsen in het programma waar de functie gebruikt wordt.

Tijdens de oefeningen maakte je reeds gebruik van functieargumenten en vulde je het instructieblok van de functie aan. Ook gebruikte je reeds return om een functieresultaat af te leveren. Je zal deze zaken dus zeker herkennen in wat volgt.

Opmerking: de termen ‘functie’ en ‘method’ worden vaak door elkaar gebruikt, maar duiden op hetzelfde.

Bij het ontwerpen van functies kan het snel fout gaan. Om een zo flexibel mogelijk inzetbare functie te maken, beperk je de functie tot één functionaliteit. Bijvoorbeeld: maak geen functie die de oppervlakte van een cirkel berekent en deze op het scherm toont, maar maak een functie die de oppervlakte van de cirkel berekent en deze als functiewaarde aflevert. Op deze manier kan je de oppervlakte niet enkel tonen, maar ook nog voor andere doeleinden gebruiken.

Opbouw van een functie

Als voorbeeldfunctie gebruiken we de functie CalcNumbers die:

  • De som maakt van de twee functieargumenten indien het eerste functieargument groter is dan of gelijk is aan het tweede.
  • Het verschil maakt van de twee functieargumenten indien het eerste functieargument kleiner is dan het tweede.
  • Het functieresultaat is het resultaat van de gemaakte bewerking.
public static int CalcNumbers(int number1, int number2)
{
    int result = 0;
    if (number1 >= number2)
    {
        result = number1 + number2;
    }
    else
    {
        result = number1 - number2;
    }
    return result;
}

Welke onderdelen vinden we in dit voorbeeld terug:

  • public: de functie is van ‘buitenaf’ toegankelijk, zo kan de functie bijvoorbeeld opgeroepen worden in de Main of in een andere functie. Voorlopig zijn alle functies die we maken public. Als we later in de cursus met classes gaan werken, wordt dit verder uitgediept.
  • static: zorgt ervoor dat de functie opgeroepen kan worden zonder dat er een object van de klasse gemaakt is.
  • int: het returntype van de functie. In bovenstaand voorbeeld levert de functie een integer als resultaat af.
  • CalcNumber: naam van de functie. We spreken af dat functies een duidelijke naam krijgen die aangeeft wat de functie doet.
  • (): na de functienaam vinden we ronde haakjes. Deze haakjes kunnen leeg zijn of er kunnen functieargumenten meegegeven worden. (zie voorbeelden)
  • {}: het instructieblok van de functie bevindt zich tussen accolades. Het instructieblok bevat de instructies die uitgevoerd zullen worden wanneer de functie aangeroepen wordt.

De functieaanroep

Je kan een functie laten uitvoeren door een functieaanroep. Deze functieaanroep kan in Main of in een andere functie gebeuren. Enkele manieren om de functie CalcNumbers aan te roepen vind je in de voorbeelden hieronder:

static void Main(string[] args)
{
    int calculatedResult = 0;

    // Aanroepen van de functie met de argumenten 5 en 7. 
    // Deze volgorde wordt gebruikt bij het initialiseren van de functieargumenten.
    // Deze functieaanroep heeft volgende initialisaties tot gevolg:
    // number1 = 5
    // number2 = 7
    // Merk op dat het functieresultaat (de returnwaarde) van de functie 
    // opgevangen wordt in de variabele calculatedResult.
    calculatedResult = CalcNumbers(5, 7);

    // Aanroepen van de functie met andere waarden voor de argumenten: 20 en 3.
    // Deze functieaanroep heeft volgende initialisaties tot gevolg:
    // number1 = 20
    // number2 = 3
    calculatedResult = CalcNumbers(20, 3);
  
    // Soms vind je onderstaande, alternatieve notatie voor de functieaanroep terug. 
    // Bij deze syntax speelt de volgorde van de functieargumenten tussen haakjes geen rol 
    // omdat de naam van het functieargument mee vermeld wordt. Deze manier van functieaanroep, 
    // met expliciete vermelding van de naam van de argumenten valt onder 
    // de naam 'named parameters'.
    calculatedResult = CalcNumbers(number2: 10, number1: 8);

    // Er ook variabelen als functieargumenten gebruikt worden. Natuurlijk  
    // moeten deze variabelen reeds op voorhand geïnitialiseerd zijn. Een functieaanroep, met  
    // gebruik van variabelen als functieargumenten, vind je hieronder.
    int value1 = 10; // Deze initialisaties gebeuren
    int value2 = 4;  // ergens in het programma voorafgaand aan de functieaanroep.
    calculatedResult = CalcNumbers(value1, value2);

    Console.ReadKey();
}

Optionele (of default) argumenten

Het is mogelijk om voor één, meerdere of alle functieargumenten een default waarde mee te geven. Indien bij de functieaanroep geen waarde voor deze functieargumenten meegegeven wordt, dan wordt de default waarde gebruikt. Aangezien het niet meer noodzakelijk is om een functieargument, waarvoor een default waarde voorzien is, een waarde te geven bij de functieaanroep spreken we hier van een optioneel argument.

Voorbeeld: Veronderstel dat de functie CalcNumbers vaak opgeroepen wordt met de waarde 10 voor het functieargument number2. Dan kan de waarde 10 reeds als default waarde bij het functieargument number2 vermeld worden bij de functie. De functie CalcNumbers ziet er dan als volgt uit:

public static int CalcNumbers(int number1, int number2 = 10) // default waarde voor number2
{
    int result = 0;
    if (number1 >= number2)
    {
        result = number1 + number2;
    }
    else
    {
        result = number1 - number2;
    }
    return result;
    }
}

De functie CalcNumbers kan nu op volgende manieren aangeroepen worden:

static void Main(string[] args)
{
   int calculatedResult = 0;

   // Met gebruik van de default waarde voor functieargument number2.
   // Deze functieaanroep heeft volgende initialisaties tot gevolg:
   // number1 = 20
   // number2 = 10
   calculatedResult = CalcNumbers(20); 

   // Zonder gebruik van de default waarde voor functieargument number2.
   // Indien er een waarde voor een optioneel argument meegegeven wordt bij de
   // functieaanroep dan heeft dit voorrang op de default waarde.
   // Deze functieaanroep heeft volgende initialisaties tot gevolg:
   // number1 = 20
   // number2 = 7
   calculatedResult = CalcNumbers(20, 7); 
   
   Console.ReadKey();
}

Let er steeds op dat je bij het schrijven van een functie de optionele argumenten als laatste vermeldt in de lijst met functieargumenten. Het is immers niet toegelaten posities van argumenten over te slaan bij de functieaanroep. Bijgevolg moeten de optionele argumenten als laatste vermeld worden.

Open het project oefening functies 1 en maak oefenreeks 1

Function overloading

Een functie wordt gedefinieerd door zijn naam en zijn lijst van argumenten. Elke functie moet uniek gedefinieerd zijn, zodat er geen dubbelzinnigheid ontstaat en de compiler weet welke functie er voor een functieaanroep gebruikt moet worden. Toch zal je soms meerdere keren dezelfde naam voor een functie willen gebruiken. Dit kan, zolang je op een andere manier een duidelijk onderscheid maakt tussen functies met dezelfde naam. Het is immers noodzakelijk dat de compiler weet welke functie er wanneer gebruikt moet worden en dit kan nu niet meer bepaald worden a.h.v. de functienaam. Bij functies met dezelfde naam kan je dit onderscheid als volgt inbouwen:

  • elke functie heeft een verschillend aantal functieargumenten.
  • elke functie heeft een verschillend type van functieargumenten.

Op bovenstaande manier unieke functies met dezelfde naam creëren is function overloading.

Voorbeeld: function overloading a.h.v. het aantal functieargumenten

Als eenvoudig voorbeeld maken we een functie die nagaat of een aantal getallen gelijk zijn. Deze getallen worden als functieargumenten aan de functie doorgegeven. De functie geeft true indien de getallen gelijk zijn, false indien de getallen niet gelijk zijn. Soms zullen er drie getallen vergeleken moeten worden, soms vier. De getallen zijn steeds van het type integer.

class Program
{
    // Versie 1: functie met 3 functieargumenten
    public static bool CompareNumbers(int n1, int n2, int n3)
    {
        bool equal = false;
        if (n1 == n2 && n2 == n3 && n1 == n3)
        {
            equal = true;
        }
        return equal;
    }

    // Versie 2: functie met 4 functieargumenten
    public static bool CompareNumbers(int n1, int n2, int n3, int n4)
    {
        bool equal = false;
        if (n1 == n2 && n2 == n3 && n1 == n3 && n1 == n4 && n2 == n4 && n3 == n4)
        {
            equal = true;
        }
        return equal;
    }


    static void Main(string[] args)
    {
        // Functieaanroep met 3 functieargumenten 
        // -> functie 1 wordt aangeroepen.
        if (CompareNumbers(5, 3, 7))
        {
            // bijbehorend instructieblok
        }

        // Functieaanroep met 3 functieargumenten 
        // -> functie 2 wordt aangeroepen.
        if (CompareNumbers(1, 5, 2, 9))
        {
            // bijbehorend instructieblok
        }

        Console.ReadKey();
    }
}

Voorbeeld: function overloading a.h.v. het type functieargumenten

Als eenvoudig voorbeeld maken we een functie Sort die van een aantal gehele getallen het grootste of van een aantal woorden het laatste in het alfabet als resultaat geeft.

Opmerking: Bij versie twee van de functie Sort gebruiken we een method uit de class string, namelijk Compare. Deze method levert -1 af als het eerste argument alfabetisch voor het tweede argument komt.

class Program
    {
        // Versie 1: functie met 3 integers als functieargumenten
        public static int Sort(int v1, int v2, int v3)
        {
            int max = v1;
            if (v2 > max)
            {
                max = v2;
            }
            if (v3 > max)
            {
                max = v3;
            }
            return max;
        }

        // Versie 2: functie met 3 strings als functieargumenten
        public static string Sort(string v1, string v2, string v3)
        {
            string max = v1;
            if (string.Compare(max, v2)==-1)
            {
                max = v2;
            }
            if (string.Compare(max, v3) == -1)
            {
                max = v3;
            }
            return max;
        }


        static void Main(string[] args)
        {
            // Functieaanroep met 3 gehele getallen als functieargumenten 
            // -> functie 1 wordt aangeroepen.
           
            int largestNumber = Sort(2, 20, 7);

            // Functieaanroep met 3 strings als functieargumenten 
            // -> functie 2 wordt aangeroepen.
           
            string lastAlphabet = Sort("John", "Steve", "Bill");

            Console.WriteLine("The largest number: {0}", largestNumber);
            Console.WriteLine("The last name alphabetically: {0} ", lastAlphabet);
            Console.ReadKey();
        }
    }
}

Open het project oefening functies 1 en maak oefenreeks 2


Previous section:
Next section:
Navigatie