Opdrachten meerdere keren uitvoeren

In bepaalde situaties kan het handig zijn om bepaalde code meerdere keren te kunnen uitvoeren, meestal onder bepaalde voorwaarden. Denk bijvoorbeeld aan een CheckBoxList of een ListBox met meerdere selecties. Daaruit moet u kunnen opvragen welke elementen geselecteerd zijn, en is het dus noodzakelijk om door de Items collectie te bladeren. Omdat u meestal niet bij voorbaat weet hoeveel en welke elementen de Items collectie bevat, heeft u een generieke manier nodig om de elementen te kunnen uitlezen. In zo'n situatie kunt u gebruik maken van zogenaamde Loops. Een Loop voert een blok met code meerdere malen uit, waarbij telkens gekeken wordt of er aan een bepaalde voorwaarde voldaan is (bijvoorbeeld dat alle elementen zijn afgehandeld). Als aan de voorwaarde voldaan is, wordt verder gegaan met de code na de Loop. De code die telkens uitgevoerd wordt is in zeker mate generiek, zodat het bijvoorbeeld de verschillende elementen kan uitlezen met dezelfde code. Hoewel de verschillende talen verschillende constructies hebben, zijn er in feite 3 verschillende soorten te onderscheiden:

In feite zijn de eerste twee soorten een specifieke vorm van de laatste, maar ze zijn zo belangrijk dat er aparte constructies voor zijn. We bespreken de verschillende constructies hieronder.

For-loop

Een For-loop voert een blok code een van te voren bepaald aantal keer uit. Van te voren wil hier zeggen op het moment dat de For-loop begint. Het hoeft dus niet zo te zijn dat u als programmeur al bepaalt hoeveel keer de code wordt uitgevoerd, maar het kan dus bijvoorbeeld aan de hand van een aantal elementen. Dit alles gebeurt op basis van een index die telkens opgehoogd wordt. Voor deze index wordt een begin- en eindwaarde opgegeven, en de iteratie begint bij de beginwaarde en eindigt wanneer de eindwaarde bereikt is. We laten dit aan de hand van een voorbeeld zien.

VB.NET

<%@ Page Language="VB" %>
<script runat="server">
  Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs)
    Dim i As Integer
    Dim Tekst As String = "U heeft geselecteerd:"
      
    For i = 0 To ListBox1.Items.Count - 1
      If ListBox1.Items(i).Selected Then
        Tekst = Tekst & "<br>- " & ListBox1.Items(i).Text
      End If
    Next
      
    Label1.Text = Tekst
  End Sub
</script>
<html>
<head>
</head>
<body>
  <form runat="server">
    <p>
      <asp:ListBox id="ListBox1" runat="server" SelectionMode="Multiple" Rows="3" AutoPostBack="True" OnSelectedIndexChanged="ListBox1_SelectedIndexChanged">
        <asp:ListItem Value="1">ASP.NET Web Matrix Project</asp:ListItem>
        <asp:ListItem Value="2">Visual Studio .NET</asp:ListItem>
        <asp:ListItem Value="3">Notepad</asp:ListItem>
      </asp:ListBox>
    </p>
    <p>
      <asp:Label id="Label1" runat="server"/>
    </p>
  </form>
</body>
</html>

C#

<%@ Page Language="C#" %>
<script runat="server">
  void ListBox1_SelectedIndexChanged(Object sender, EventArgs e) {
    int i;
    string Tekst = "U heeft geselecteerd:";
      
    for(i = 0; i < ListBox1.Items.Count; i++) {
      if(ListBox1.Items[i].Selected) {
        Tekst = Tekst + "<br>- " + ListBox1.Items[i].Text;
      }
    }
      
    Label1.Text = Tekst;
  }
</script>
<html>
<head>
</head>
<body>
  <form runat="server">
    <p>
      <asp:ListBox id="ListBox1" runat="server" SelectionMode="Multiple" Rows="3" AutoPostBack="True" OnSelectedIndexChanged="ListBox1_SelectedIndexChanged">
        <asp:ListItem Value="1">ASP.NET Web Matrix Project</asp:ListItem>
        <asp:ListItem Value="2">Visual Studio .NET</asp:ListItem>
        <asp:ListItem Value="3">Notepad</asp:ListItem>
      </asp:ListBox>
    </p>
    <p>
      <asp:Label id="Label1" runat="server"/>
    </p>
  </form>
</body>
</html>

De bovenstaande code geeft een ListBox control weer waarin meerdere selecties gemaakt kunnen worden. Verder geeft het een Label control weer waarin aangegeven wordt wat de gebruiker geselecteerd heeft. Als de selectie wijzigt, vindt een automatische postback plaats, en wordt de script code uitgevoerd. Hierin worden eerst twee variabelen gedeclareerd, een index voor de For-loop en een tijdelijke variabele voor de tekst die in de Label control moet worden weergegeven. Vervolgens wordt er door de elementen in de ListBox control heen gelopen met de For-loop, en wordt tekst toegevoegd voor ieder element dat geselecteerd is. Merk op dat daarvoor steeds dezelfde variabele gebruikt wordt. Dit kan omdat de expressie rechts van het =-teken geδvalueerd wordt voordat het resultaat van die expressie aan de variabele wordt toegekend. Merk ook op dat in de toegevoegde waarde ook HTML staat. Hoeveel iteraties er moeten zijn wordt bepaald door ListBox1.Items.Count. Dit geeft het aantal elementen aan dat in de ListBox control zit. Omdat die elementen geteld worden vanaf 0, wordt er geteld van 0 tot en met 2, en wordt in VB.NET tot en met ListBox1.Items.Count - 1 gewerkt. In C# wordt aangegeven dat de index kleiner moet blijven dan ListBox1.Items.Count, hetgeen hetzelfde effect heeft. Bovendien wordt er in C# met i++ aangegeven dat de index na elke iteratie met 1 opgehoogd moet worden. De elementen in de ListBox control worden vervolgens op hun index uitgelezen. Het resultaat ziet u in figuur 1.


Figuur 1, ListBox control die met een For-statement wordt uitgelezen.

Zowel in VB.NET als C# kunt u manipuleren met hoeveel tegelijk de index ophoogt, en of er omhoog of omlaag geteld wordt. Aangezien dit meestal niet van toepassing is, zullen we dat hier niet verder bespreken.

For Each-loop

Een For Each-loop is vrijwel hetzelfde als een For-loop. Het verschil is dat u niet met een index werkt, maar dat de For Each-loop automatisch voor elk element uit een collectie of array de code uitvoert. Bij een For Each-loop wordt telkens een element uit de collectie of lijst gehaald, die u in de code kunt manipuleren onder een generieke naam. De code hieronder laat dit zien.

VB.NET

Dim Item As ListItem
      
For Each Item In ListBox1.Items
  If Item.Selected Then
    Tekst = Tekst & "<br>- " & Item.Text
  End If
Next

C#

foreach(ListItem Item in ListBox1.Items) {
  if(Item.Selected) {
    Tekst = Tekst + "<br>- " + Item.Text;
  }
}

De code hierboven is een alternatief voor de For-loop die we eerder gebruikt hebben. Er wordt een variabele Item (dit kan ook een andere naam zijn) declareerd van het type ListItem, het type element van een ListBox control of een van de andere List controls. Bij iedere iteratie wordt een element uit de Items collectie van de ListBox toegekend aan de variabele Item. Via de variabele kunt u vervolgens de eigenschappen van het betreffende element uitlezen, in plaats van dat u een index moet gebruiken. Merk op dat in C# de variabele niet apart gedeclareerd wordt, maar als onderdeel van de For Each-loop. In VB.NET kan dit niet, en moet u de variabele dus declareren voordat u de For Each-loop kunt gebruiken.

Do/While-loops

Do/While-loops voeren een blok code uit totdat er aan een bepaalde voorwaarde is voldaan (of zolang een bepaalde voorwaarde geldt). Dit gebeurt aan de hand van een expressie zoals die ook gebruikt kan worden in een If-statement. In veel gevallen is er een beter alternatief voor een Do/While-loop, maar omdat het in sommige gevallen toch handig is, laten we het hier toch zien, en wel aan de hand van een voorbeeld. In het voorbeeld wordt gezocht in een bestand naar de landcodes van Nederland in een bestand met landcodes zoals hieronder:

NAURU|NR|NRU|520
NEPAL|NP|NPL|524
NETHERLANDS|NL|NLD|528
NETHERLANDS ANTILLES|AN|ANT|530
NEW CALEDONIA|NC|NCL|540
NEW ZEALAND|NZ|NZL|554

Er wordt telkens een regel uit het bestand gelezen, en die wordt naar een array gesplitst waaruit vervolgens de landnaam uitgelezen wordt (index 0 in de array). Is de landnaam gelijk aan NETHERLANDS, dan worden de landcodes in Label controls geplaatst. De gehele code ziet u hieronder.

VB.NET

<%@ Page Language="VB"%>
<%@ Import Namespace="System.IO"%>
<script runat="server">
  Sub Page_Load(sender As Object, e As EventArgs)
    If Not Page.IsPostBack Then
      Dim Bestandsnaam As String = Server.MapPath("landen.txt")
      Dim Bestand As New StreamReader(Bestandsnaam)
      
      Do While Bestand.Peek() > -1
        Dim Land As String = Bestand.ReadLine()
        
        If Land.Split("|")(0) = "NETHERLANDS" Then
          Label1.Text = Land.Split("|")(1)
          Label2.Text = Land.Split("|")(2)
          Label3.Text = Land.Split("|")(3)
          Exit Do
        End If
      Loop
      
      Bestand.Close()
    End If
  End Sub
</script>
<html>
<head>
</head>
<body>
  <form runat="server">
    Land codes:<br />
    <asp:Label id="Label1" runat="server"/><br />
    <asp:Label id="Label2" runat="server"/><br />
    <asp:Label id="Label3" runat="server"/>
  </form>
</body>
</html>

C#

<%@ Page Language="C#"%>
<%@ Import Namespace="System.IO"%>
<script runat="server">
  void Page_Load(Object sender, EventArgs e) {
    if(!Page.IsPostBack) {
      string Bestandsnaam = Server.MapPath("landen.txt");
      StreamReader Bestand = new StreamReader(Bestandsnaam);
      
      while(Bestand.Peek() > -1) {
        string Land = Bestand.ReadLine();
        
        if(Land.Split('|')[0] == "NETHERLANDS") {
          Label1.Text = Land.Split('|')[1];
          Label2.Text = Land.Split('|')[2];
          Label3.Text = Land.Split('|')[3];
          break;
        }
      }
      
      Bestand.Close();
    }
  }
</script>
<html>
<head>
</head>
<body>
  <form runat="server">
    Land codes:<br />
    <asp:Label id="Label1" runat="server"/><br />
    <asp:Label id="Label2" runat="server"/><br />
    <asp:Label id="Label3" runat="server"/>
  </form>
</body>
</html>

De code hierboven verdient enige uitleg. Ten eerste gebruiken we de functie Server.MapPath om het bestand landen.txt te vinden. Met Server.MapPath wordt het virtuele pad (het pad binnen de website) vertaald naar een fysiek pad (het daadwerkelijke pad op de harde schrijf) in de vorm van c:\pad...\landen.txt. Ten tweede wordt een StreamReader aangemaakt waarmee het bestand uitgelezen kan worden. Met ReadLine kunnen we telkens een regel lezen, en met Peek kunnen we kijken of er nog wel een volgende regel is. Is er geen volgende regel meer, dan wordt de loop beδindigd. Anders wordt de loop met Exit Do of break beδindigd als de landcodes gevonden zijn. Het resultaat is een simpele lijst met de landcodes NL, NLD, en 528.

Een Do/While-loop zoals hierboven wordt nul of meer keer uitgevoerd. Er zijn ook gevallen waarin u de code minimaal een keer uitgevoerd wilt hebben. In dat geval kunt u de evaluatie pas na de loop laten uitvoeren, zoals in de voorbeeldcode hieronder.

VB.NET

Do
  'voer hier code uit
Loop While voorwaard

C#

do {
  //voer hier code uit
} while(voorwaarde);

⌐2002 Microsoft Nederland BV