C# Metoder
Inledning
När programmen blir större och mer komplicerade är det bra att kunna dela upp programmet i olika delar som gör specifika saker, vilket kan göra programmet mer lättläst. Ett sätt är att använda metoder, som är en mycket viktig byggsten" i C#. En metod kan ses som ett litet "program i programmet". Det är en programslinga som man anropar från huvudprogrammet, och eventuellt skickar med några invärden som metoden ska jobba med. Metoden utför då en uppgift eller returnerar ett svarsvärde. Man brukar dela in metoder i några olika grupper.
Värdeanrop
Metoder som returnerar ett värde (och med parametrar)
Vi är egentligen bara intresserade av att skicka information (ett eller flera värden) till en metod som gör
vissa beräkningar med hjälp av dessa värden och sen returnerar ett värde som är resultatet av dessa
bearbetningar. En metod är lite kod som gör något. Vi skickar in ett eller flera argument och metoden
returnerar ett värde. T.ex. kan koden se ut på följande sätt:
int summa( int a, int b) //huvud
{
return a+b; //kropp
}
Summa är metodens namn, som man använder när man ropar på den från huvudprogrammet. Före
metodens namn står vilken typ av svar metoden kommer att lämna, i vårt fall ett heltal (int).
Efter metodens namn skrivs inom parentes en lista på de invärden eller parametrar, som metoden
behöver för att kunna göra sitt jobb. I vår metod är invärdena heltalen a och b.
Return avslutar metoden och skickar tillbaka det resultat som metoden gav, det vill säga vårt returvärde. Värdet som returneras av
return ska vara av samma typ som metodens typ, här int.
Man ropar sedan på metoden med dess namn och de parametrar som behövs.
Ett litet exempel med en metod
//Metoder Ex 1:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Metoder1
{
class Program
{
//OBS! Placering av funktionen bör ske direkt efter klass definitionen
//static används när vi kör "Console Application"
static int summa( int a, int b)
{
return a+b;
}
static void Main(string[] args)
{
//variabler
int x, y, z;
Console.WriteLine("Skriv in två tal: ";
x = Convert.ToInt32(Console.ReadLine());
y = Convert.ToInt32(Console.ReadLine());
z = summa(x,y); //Värdet från x kopieras över till a och y till b
Console.WriteLine("Summan är "+z);
Console.ReadKey();
}
}
}
Variablerna a och b är bara synliga i metoden, och existerar inte utanför den, t.ex. i main(). Att värdet från x kopieras över till a och y till b, kallas värdeanrop. Om vi skulle ändra värdet av a och b i metoden summa, skulle alltså inte originalvärdena x och y ändras, bara kopiorna a och b. Motsatsen till värdeanrop är referensanrop, vilket innebär att a bara blir ett "alias" för x, fast de egentligen är samma värde i datorns minne. Det innebär att om jag ändrar a ändras också x o.s.v. Det ska vi titta på längre ner.
Metoder som inte returnerar ett värde (och utan parametrar)
Funktionen ovan gav ett heltal till svar. Man kan naturligtvis skriva funktioner som returnerar double,
char, long int etc, men man kan också skriva funktioner som inte returnerar något svarsvärde. Ett
exempel:
void meny()
{
Console.WriteLine("MENY");
}
void står för "tomrum", så här ska inget värde returneras. Dessutom är parentesen för invärden tom, vilket är ett förkortat skrivsätt för void meny(void), d.v.s. inga argument skickas med när vi anropar metoden.
Metoder med defaultvärde
Default-värden på parametrar, d.v.s. att i metoddeklarationen ange värden för parametrarna
som ska antas om inget värde lämnas vid metodanropet Ett
exempel på en sådan metod:
void skriv_ut(double tal, int n=1)
{
for (int i = 1; i <= n; i++)
Console.WriteLine( tal );
}
Metoden anropas med t ex med
skriv_ut(resultat);
eller
skriv_ut(resultat,4);
Ett exempel med olika varianter av metoder
//Metoder Ex 2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Metoder_Ex_2
{
class Program
{
//******************************************************
//alla funktioner
//******************************************************
static void meny()
{
Console.WriteLine("\n\n***** MENY *****");
Console.WriteLine("################");
Console.WriteLine(" 1 beräkna medelvärde");
Console.WriteLine(" 2 beräkna maxvärde");
Console.WriteLine(" 0 AVSLUTA \n");
}
//******************************************************
static int las_in_alternativ()
{
int svar;
Console.WriteLine("\n Ange alternativ: ");
svar = Convert.ToInt32(Console.ReadLine());
return svar;
}
//******************************************************
static double medelvarde()
{
double tal1, tal2;
Console.WriteLine(" Ange två tal: ");
tal1 = Convert.ToDouble(Console.ReadLine());
tal2 = Convert.ToDouble(Console.ReadLine());
Console.WriteLine();
return (tal1 + tal2) / 2.0;
}
//******************************************************
static double max(double tal1, double tal2)
{
if (tal1 > tal2) return tal1;
else return tal2;
}
//******************************************************
static void skriv_ut(double tal, int n=1)
{
for (int i = 1; i <= n; i++)
Console.WriteLine( tal );
}
//******************************************************
//******************************************************
static void Main(string[] args)
{
double tal1, tal2, resultat;
int svar = 1;
while (svar != 0)
{
meny();
svar = las_in_alternativ();
Console.Clear( );
if (svar == 1)
{
resultat = medelvarde();
Console.WriteLine(" Medelvarde : " + resultat);
skriv_ut(resultat);
Console.WriteLine();
skriv_ut(resultat, 4);
}
else if (svar == 2)
{
Console.WriteLine(" Ange två tal: ");
tal1 = Convert.ToDouble(Console.ReadLine());
tal2 = Convert.ToDouble(Console.ReadLine());
resultat = max(tal1, tal2);
Console.WriteLine("\n Maxvarde : " + resultat);
}
else if (svar != 0)
{
Console.WriteLine("\n Felaktigt val! \n");
}
}
Console.WriteLine(" HEJ DÅ");
Console.ReadKey();
}
}
}
Kommando för att rensa skärmen i vår "Console Application"
Console.Clear( );
Referensanrop
De metoder som du skrivit hittills har använt s.k. värdeanrop, d.v.s. de argument som skickats med till
metoden har kopierats till för metoden egna lokala kopior av variablerna. De förändringar av värdena
som gjorts i metoderna har då bara påverkat metodens kopior, inte de ursprungliga variablerna i
huvudprogrammet. Du ska nu få lära dig ett specialfall av motsatsen, ett s.k. referensanrop, när de
argument man skickar till metoden i själva verket är samma variabler som huvudprogrammet använder,
fast under ett annat namn. Argumentet får alltså ett slags alias i metoden, genom att man skriver ref framför parameternamnet.
//Metoder Ex 3
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Metoder_Ex_3
{
class Program
{
static void kvadrera(ref int i) // metoden kvadrera, som tar en referens till en heltalsvariabel
{ // i är alltså ett alias för tal i huvudprogrammet, ändrar man i så ändras tal
i = i * i; // här kvadreras i, och alltså också tal i huvudprogrammet
}
static void Main(string[] args)
{
int tal = 25; // heltalsvariabeln tal sättes till 25
Console.WriteLine(tal); // 25 skrivs ut på skärmen
kvadrera(ref tal); // tal skickas som referensparameter till metoden kvadrera
Console.WriteLine(tal); // 625 skrivs ut på skärmen
Console.ReadKey();
}
}
}
Array som parameter i metodanropet
En metod som tar en array som argument blir alltid ett referensanrop. Det innebär alltså att arrayen själv
inte kommer kopieras över till ett ny array som hör till metoden (det som kallas värdeanrop, se tidigare),
utan bara minnesadressen till den första "lådan" kopieras. Det innebär att både huvudprogrammet och metoden pekar på samma utrymme i datorns arbetsminne.

Om du har läst in ovanstående värden i arrayen tallista och skickar den
void changeboxzero(int[ ] lista)
{
lista[0]=8;
}
med anropet changeboxzero(tallista), så kommer resultatet bli:

Metoden behöver alltså inte returnera någonting, utan du kan skicka med befintliga värden och få
tillbaks nya förändrade värden med en array som parameter (Referensanrop). En fördel med detta är att
metoden inte är beroende av hur lång arrayen är, utan fungerar för alla storlekar. De
tomma hakarna efter namnet tallista talar om att argumentet är ett fält och inte en vanlig variabel.
Ett exempel
//Metoder Ex 4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Metoder_Ex_4
{
class Program
{
static void changeBoxZero(int[] lista)
{
lista[0]=8;
}
static void skrivUt(int[] lista)
{
for (int i = 0; i < lista.Length; i++)
Console.Write(lista[i] + " ");
}
static void Main(string[] args)
{
int[] listaEtt = new int[]{1,2,3};
int[] listaTva = new int[]{6,5,4,3,2,1};
changeBoxZero(listaEtt);
skrivUt(listaEtt);
Console.WriteLine("\n");
changeBoxZero(listaTva);
skrivUt(listaTva);
Console.ReadKey();
}
}
}
Rekursiva metoder
En metod som anropar sig själva kallas rekursiv metod. Denna specialvariant är bra vid vissa speciella problem. En användning hittar vi vid beräkning av fakultet.
int nFakultet(int n)
{
if (n<=1) return 1;
else return n*(nFakultet(n-1);
}
Ett exempel på rekursion
//Metoder Ex 5
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Metoder_Ex_5
{
class Program
{
static int nFakultet(int n)
{
if (n<=1) return 1;
else return n*(nFakultet(n-1));
}
static void Main(string[] args)
{
int x,fak;
Console.WriteLine("Skriv in ett tal för att beräkna fakulteten:");
x=Convert.ToInt32(Console.ReadLine());
fak=nFakultet(x);
Console.WriteLine(x+"! = "+fak);
Console.ReadKey();
}
}
}
Källor
Filmer
C# Metoder Demo 1 Grundläggande om metoder (PB 12 min)
C# Metoder Demo 2 Referensanrop och array som parameter (PB 15 min)