Metoder och funktioner

Inledning

Metoder, eller funktioner som det ibland också kallas, kan vi börja att se som återvinning av kod. Istället för att skriva liknande kod på flera ställen så har vi en möjlighet att göra en metod av koden och anropa metoden varje gång istället för att skriva koden vi vill utföra om och om igen. På så sätt kan vi börja med att se det som en återvinning. Vi tar tre exempel alla gjorda för att passa "Console Application"-projekt. Förklaringar och diskussioner följer efter exemplen.

Det finns numera en videogenomgång i slutet av artikel som tar upp grundläggande saker när det gäller metoder. Du kan med fördel se videon innan du läser hela artikeln.

Exempel 1

Vi vill skriva ut alla veckodagar två gånger men inte direkt efter vartannat. Vad vi gör däremellen är ointressant. Vi börjar med koden utan någon metod:

Exempel 1 utan metod

    Console.WriteLine("Måndag");
    Console.WriteLine("Tisdag");
    Console.WriteLine("Onsdag");
    Console.WriteLine("Torsdag");
    Console.WriteLine("Fredag");
    Console.WriteLine("Lördag");
    Console.WriteLine("Söndag");

    //Här görs något annat, t.ex inmatning eller beräkningar
    //för exemplet är det inte instressant. Poängen är att
    //vi vill upprepa samma utrskift som vi gjort tidigare 
    //en gång till vid ett senare tillfälle.

    Console.WriteLine("Måndag");
    Console.WriteLine("Tisdag");
    Console.WriteLine("Onsdag");
    Console.WriteLine("Torsdag");
    Console.WriteLine("Fredag");
    Console.WriteLine("Lördag");
    Console.WriteLine("Söndag");

Koden som skriver ut veckodagarna kan vi lätt identifiera och uppmärksamma att exakt samma kod körs på två ställen. När detta inträffar att kod upprepar sig i program så bör du som programmerare vara uppmärksam. Vi bör nu "kapsla in" koden i en metod och anropa metoden istället. Komplett exempel:

Exempel 1 med metod

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exmpel1
{
    class Program
    {
        static void SkrivUtVeckodagar()
        {
            Console.WriteLine("Måndag");
            Console.WriteLine("Tisdag");
            Console.WriteLine("Onsdag");
            Console.WriteLine("Torsdag");
            Console.WriteLine("Fredag");
            Console.WriteLine("Lördag");
            Console.WriteLine("Söndag");
        }

        static void Main(string[] args)
        {
            SkrivUtVeckodagar();

            //Här görs något annat, t.ex inmatning eller beräkningar
            //för exemplet är det inte instressant. Poängen är att
            //vi vill upprepa samma utrskift som vi gjort tidigare 
            //en gång till vid ett senare tillfälle.

            SkrivUtVeckodagar();
        }
    }
}

Varje gång programmet når SkrivUtVeckodagar(); så hoppar exekveringen (programmet) in i den angivna metoden och koden som finns i metoden körs innan programmet återgår till raden för anropet och fortsätter sedan vidare därifrån.

Detta exempel använder varken in- eller utparametrar i metoden SkrivUtVeckodagar. Mer om detta efter exemplen.

Exempel 2

Säg att vi vill skriva ut texten "Hello" tio gånger, texten "world" nio gånger och texten "!" åtta gånger. Det kan vi göra på följande sätt:

Exempel 2 utan metod

    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine("Hello");
    }
    for (int i = 0; i < 9; i++)
    {
        Console.WriteLine("World");
    }
    for (int i = 0; i < 8; i++)
    {
        Console.WriteLine("!");
    }

Vi kan börja med att identifiera vad som skulle kunna återvinnas i koden. Vi gör liknande saker tre gånger, nämligen att skriva ut en text ett visst antal gånger. Här är det kanske inte lika uppenbart att vi kan ersätta detta med en metod, men det kan vi:

Exempel 2 med metod

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exmpel2
{
    class Program
    {
        static void UpprepaText(string text, int antal)
        {
            for (int i = 0; i < antal; i++)
            {
                Console.WriteLine(text);
            }
        }

        static void Main(string[] args)
        {
            UpprepaText("Hello", 10);
            UpprepaText("World", 9);
            UpprepaText("!", 8);
        }
    }
}

bild

Metoden UpprepaText löser uppgiften genom att använda två inparametrar. Inparametrarna är av typen string, för texten som skall skrivas ut, och av typen int för att ange antalet gånger som texten skall skrivas ut. Inparametrar kallas ibland för argument till metoden.

När vi använder metoden UpprepaText så måste vi ange två parametrar annars kan vi ej köra programmet. Vi skulle kunna säga att metoden kräver två inparametrar för att fungera.

Exempel 3

Nu vill vi räkna antalet ord i en text. Att räkna antalet ord i en text gör vi genom att dela texten med metoden Split som finns inbyggd i alla strängar. Vi delar på mellanslag då det är det som skiljer ord åt. Vi får sedan en array av string som vi kan undersöka längden på för att få antalet ord:

Exempel 3 utan metod

    string text = "Detta är en liten text i ett exempel.";

    string[] delar = text.Split(' ');
    int antalOrd = delar.Length;

Detta skall vi göra en metod av. Vi vill skicka in text till metoden och få ett svar på hur många ord som finns i texten tillbaka. Vi visar med ett mer komplett exempel igen:

Exempel 3 med metod

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exmpel3
{
    class Program
    {
        static int AntalOrd(string text)
        {
            string[] delar = text.Split(' ');
            return delar.Length;
        }

        static void Main(string[] args)
        {
            Console.Write("Mata in en text: ");
            string text = Console.ReadLine();

            Console.WriteLine("Du matade in " + AntalOrd(text) + " ord!");
        }
    }
}

bild

Här använde vi oss för första gången en utparameter, eller ett returvärde som det också kallas. Detta är något som metoder kan "slänga tillbaka" och som vi kan "fånga upp" därifrån vi anropade metoden.

Genomgång

Du har nu sett tre olika exempel av varierad svårighetsgrad och du kanske undrar vad som är så bra med metoder? Sanningen är den att du behöver inte skriva egna metoder men här har du några av fördelarna:

Exempel 1
+ Inkapsling av kod till funktioner innebär i förlängningen att du skriver mindre kod.
+ Mindre kod betyder färre risker att skriva fel. Även om du hade tänkt skriva samma kod på 10 ställen så kan det ändå smyga sig in ett fel någonstans.
Exempel 2
+ Metoden UpprepaText blir lättare att bryta ut och använda i kommande projekt.
+ Mindre kod
+ Minskad risk för fel.
Exempel 3
+ Koden blir tydligare att läsa och förstå då metodnamnet AntalOrd är tydligare med vad som utförs.
+ Mindre kod
+ Minskad risk för fel.
+ Lättare att återanvända

Regler för att skriva metoder

En metod deklareras på följande sätt i ett Console Application:

static returtyp MetodNamn(datatyp1 inparameternamn1, datatyp2 inparameternamn2, ...)

Arbeter du ej i ett Console Application utan kanske i ett "Windows Application"-projekt så kan du utelämna static. En synlighetsdeklaration av typen public, protected eller private kan sättas framför men liksom static och dess betydelse tas inte upp i detalj i denna artikel. För en detaljerad förklaring till static se Static och This eller OOP - Objektens liv .

Placeringen av en metod bör ske direkt under klass-definitionen. Detta är alltså FEL:

Exempel på FEL

namespace Exmpel
{
    static void DoSomething()
    {
        //Deklarerat metoden på FEL ställe!
    }

    class Program
    {
        static void Main(string[] args)
        {
            //
        }
    }
}

Detta är RÄTT:

Exempel på RÄTT

namespace Exmpel
{
    class Program
    {
        static void Main(string[] args)
        {
            //
        }

        static void DoSomething()
        {
            //Deklarerat metoden på RÄTT ställe!
        }
    }
}

Du kan deklarera hur många metoder du vill i samma klass. Deklarerar du dem med samma namn fast med olika inparametrar så gör du något som kallas för överlagrade metoder. Detta beskrivs längre fram.

Utparameter / returparameter

Utparameter eller returparameter kan du bara ha en av. I en del programspråk kan man faktiskt ha flera returparametrar men det absolut vanligaste är att språket endast tillåter en returparameter (gäller såväl C#, Java som C++).

Vanligaste anledningen till att man vill ha en returparameter är om metoden skall skapa något nytt, t.ex. ett resultat av en beräkning som i exempel 3.

Om ingen returparameter skall användas så visar vi det genom att deklarera metodens returtyp som void. Void kan översättas till svenska med tomrum, tom eller ogiltig.

Metoder som deklarerat en returtyp (annat än void) måste avslutas med return följt av en variabel eller beräkning som resulterar i samma datatyp som den angivna returtypen.

Det finns inget krav på att vi måste "fånga upp" resultatet eller ens använda oss av returparametern vid ett anrop till en metod med returparameter.

Inparametrar

Du kan ha ingen, en , två eller flera inparametrar av olika typer. Du kan alltså deklarera hur många inparametrar du vill. I exemplen ovan så använde vi t.ex. två olika inparametrar av två olika datatyper i exempel 2.

När metoden anropas måste vi skicka med inparametrar av matchande datatyper om dessa finns deklarerade.

Inparametrarna ges variabelnamn vid deklarationen. Dessa variabelnamn namnges som variabler vanligtvis görs och är endast giltiga i metoden. Datatyper av värdetyp t.ex. int, string, double, bool, med flera samt sammansatta datatyper som struct skickas som "kopior", dvs. endast värdet skickas till metoden. Datatyper av referentyp t.ex alla objekt gjorda av vanliga klasser typ Random skickas som referenser. Exempel på detta följer.

Namngivning

Du bör använda Pascal case som regel vid namngivning av metoder. Det betyder att första bokstaven i namnet alltid är en versal och varje nytt ord i metodnamnet inleds också med en versal t.ex. AntalOrd eller SkrivUtVeckodagar.

Detta är mer en estetisk regel som gör koden mer lättläst. De flesta C#-utvecklare använder sig av denna regel.

Övning 1

Skriv ett program där du deklarerar och använder en egen metod CelsiusTillFarenheit. Metoden skall omvandla grader Celsius till grader Farenheit. Metoden behöver alltså en inparameter av typen double och en utprameter av typen double. Du skickar in grader i Celsius och vill få ut ett resultat i Farenheit istället. Formeln för omvandling som du måste använda är: Farenheit = (Celsius / 5.0) * 9 + 32.

Övning 2

Skapa ett program (antingen Console eller Windows) där du matar in radien på en cirkel. Programmet skall sedan räkna ut både area och omkrets på cirkeln. Till beräkningarna skall du använda dig av metoder, en för areaberäkningen och en för beräkningen av omkretsen. Tips: runda gärna av till två decimaler med Math.Round(). Exempel på Console Application:

bild

Övning 3

I rollspel brukar tärningsslag beskrivas som "1T6" vilket betyder att en tärning med 6 sidor skall kastas en gång. Ibland skall en tärning kastas flera gånger t.ex. "3T6" vilket betyder 3 kast med en vanlig tärning. Skriv ett program (Console eller Windows) där du skapar en metod KastaTärning som har en inparameter för hur många gånger tärningen skall kastas. Resultatet skall returneras. Vi förutsätter en vanlig 6-sidig tärning. Klassen Random måste användas. Tänk på att 3 kast med en tärning inte är samma sak som att slumpa mellan 3 och 18. Du måste slumpa mellan 1 och 6 tre gånger. Exempel på Console Application:

bild

Överlagrade metoder

En metod kan kallas överlagrad då den bär samma namn som en tidigare deklarerad metod i samma klass. Hur är det möjligt? Jo, det går inte att deklarera två exakt likadana metoder utan de måste skilja på antalet inparametrar eller vilka datatyper som används för inparametrarna.

Vi tar ett exempel där en metod med samma namn (DoSomething) deklareras fyra gånger:

Exempel på överlagring

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exmpel
{
    class Program
    {
        static void Main(string[] args)
        {
            DoSomething();
            DoSomething(5);
            DoSomething(5.0);
            DoSomething(3, "hej");
        }

        static void DoSomething()
        {
            //Ingen inparameter alls
        }
        static void DoSomething(int i)
        {
            //Inparameter av typen int
        }
        static void DoSomething(double i)
        {
            //Inparameter av typen double
        }
        static void DoSomething(int i, string s)
        {
            //Två inparametrar
        }
    }
}

I exemplet ovan anropas även varje meod en gång från Main-metoden. Det är viktigt att veta att det är just inparametrarna som avgör vilken metod som används. Skillnaden mellan 5 och 5.0 är att 5.0 är ett decimaltal (double), därför anropas metoden med en double som inparameter och inte den med int.

I Visual Studio kan du märka att det finns överlagrade metoder på ett trevligt sätt. När du skriver "(" efter ett metodnamn, som i vårt exempel DoSomething( så visar Visual Studio en lista på alla olika sätt du kan anropa metodennamnet på. I vårt exempel ser det ut som:

bild

I listan ser vi nu att vi har 4 olika alternativ på överlagrade metoder med samma namn. Bläddrar vi mellan dem med pilarna så får vi snabbt information om vad som skall skickas som inparametrar för att vi skall kunna använda metod-alternativet. Detta har du säkert sett tidigare och faktum är att de flesta metoder som finns i .NET är oftast överlagrade. Ta i princip valfri metod i en string, t.ex. Split så märker du att det finns alternativa sätt, dvs. överlagrade metoder.

Övning 4

Bygg vidare på övning 3 och skapa en överlagrad metod till KastaTärning. Den nya varianten skall ha både antalet sidor på tärningen som skall kastas samt antalet gånger tärningen skall kastas som inparametrar. Dvs. du skall kunna slå "3T6" eller "2T20" om du så vill med att anropa KastaTärning(6, 3) eller KastaTärning(20, 2). Resultatet skall givetvis returneras från metoden.

Övning 5

Bygg vidare på övning 4 och skapa ytterligare en överlagrad metod till KastaTärning. Denna gång skall inparametern vara av typen string. Du skall nämligen direkt kunna tolkas texten "3T6", "2T4" eller "1T20" som ett tärningskast och returnera resultatet. Här krävs lite stränghantering men ett tips kan vara att använda Split på bokstaven "T"..

Ytterligare tips till övning 4 och 5 är att du kan återanvända tidigare överlagrade metoder i de nya metoderna. Skapar du metoden i övning 4 så har du princip löst övning 3 också. Kasta en "vanlig" tärning blir samma sak som att anropa metoden i övning 4 som KastaTärning(6, 1). Du kan alltså från en överlagrad metod anropa en annan metod. Problemet med övning 5 blir då att tolka texten, t.ex. "3T6" till ett anrop till metoden från övning 4 med KastaTärning(6, 3). På så vis kan du återanvända metoder från en överlagrad metod och du slipper skriva liknande kod på flera ställen.

Videogenomgång

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *

Scroll to top