# Interfaces in de praktijk

De bestaande .NET klassen gebruiken vaak interfaces om bepaalde zaken uit te voeren. Zo heeft .NET tal van interfaces gedefiniëerd (bv. `IEnumerable`, `IDisposable`, `IList`, `IQueryable` enz.) waar je zelfgemaakte klassen mogelijk aan moeten voldoen indien ze bepaalde bestaande methoden wensen te gebruiken.

Een typisch voorbeeld is het gebruik van de `Array.Sort` methode. Hier wordt het echte nut van interfaces erg duidelijk: de ontwikkelaars van .NET kunnen niet voorspellen hoe andere ontwikkelaars hun bibliotheken gaan gebruiken. Via interfaces geven ze als het ware krijtlijnen en vanaf dan moeten de ontwikkelaars zelf maar bepalen hoe hun nieuwe klassen zullen samenwerken met die van .NET.

## Sorteren met Array.Sort en de IComparable interface

Een veelgebruikte .NET interface is de `IComparable` interface. Deze wordt gebruikt indien .NET bijvoorbeeld een array van objecten wil sorteren. Bij wijze van demonstratie zal ik demonstreren waarom deze interface erg nuttig kan zijn.

### Stap 1: Het probleem

**Indien je een array van objecten hebt en je wenst deze te sorteren via `Array.Sort` dan dienen de objecten de `IComparable` interface te hebben.**

We willen een array van landen kunnen sorteren op grootte van oppervlakte.

Stel dat we de klasse `Land` hebben:

```csharp
internal class Land
{
    public string Naam {get;set;}
    public int Oppervlakte {get;set;}
    public int Inwoners {get;set;}
}
```

We plaatsen 3 landen in een array:

```csharp
Land[] eurolanden = new Land[3];
eurolanden[0] = new Land() {Naam = "België", Oppervlakte = 5, Inwoners = 2000};
eurolanden[1] = new Land() {Naam = "Frankrijk", Oppervlakte = 7, Inwoners = 2500};
eurolanden[2] = new Land() {Naam = "Nederland", Oppervlakte = 6, Inwoners = 1800};
```

Wanneer we nu zouden proberen de landen te sorteren:

```csharp
Array.Sort(eurolanden);
```

Dan treedt er een uitzondering op:`InvalidOperationException: Failed to compare two elements in the array`. Dit is erg logisch: .NET heeft geen flauw benul hoe objecten van het type `Land` moeten gesorteerd worden. Moet dit alfabetisch volgens de `Naam` property, of van groot naar klein op aantal `Inwoners`? Enkel jij als ontwikkelaar weet momenteel hoe er gesorteerd moet worden.

### Stap 2: IComparable onderzoeken

We kunnen dit oplossen door de `IComparable` interface in de klasse `Land` te implementeren. We bekijken daarom eerst de documentatie van deze interface[^1]. De interface is beschreven als:

```csharp
interface IComparable
{
    int CompareTo(Object obj);
}
```

{% hint style="danger" %}
**OPGELET: Deze interface bestaat al in .NET en mag je dus niet opnieuw in code schrijven!**
{% endhint %}

Daarbij moet de methode een `int` teruggeven als volgt:

| Waarde              | Betekenis                                                  |
| ------------------- | ---------------------------------------------------------- |
| Getal kleiner dan 0 | Huidig object komt **voor** het `obj` dat werd meegegeven. |
| 0                   | Huidig object komt op **dezelfde** positie als `obj`.      |
| Getal groter dan 0  | Huidig object komt **na** `obj`.                           |

De `Array.Sort` methode zal werken tegen deze `IComparable` interface om juist te kunnen sorteren. Het verwacht dat de klasse in kwestie een `int` teruggeeft volgens de afspraken van de tabel hierboven.

### Stap 3: IComparable in Land implementeren

We zorgen er nu voor dat `Land` deze interface implementeert. Daarbij willen we dat *de landen volgens oppervlakte worden gesorteerd* :

```csharp
internal class Land: IComparable
{
    public int CompareTo(object obj)
    {
        Land temp =  obj as Land;
        if(temp != null)
        {  
            if(Oppervlakte > temp.Oppervlakte) 
                return 1;
            if(Oppervlakte < temp.Oppervlakte) 
                return -1;
            return 0;
        }
        else
            throw new NotImplementedException("Object is not a Land"); 
    }
}
```

Nu zal de `Sort` werken:

```csharp
Array.Sort(eurolanden);
```

De `Sort()`-methode kan nu ieder object bevragen via de `CompareTo()`-methode en zo volgens een eigen interne sorteeralgoritme de landen in de juiste volgorde plaatsen.

Stel dat vervolgens nog beter willen sorteren: *we willen dat landen met een gelijke oppervlakte, op hun aantal inwoners gesorteerd worden*:

```csharp
public int CompareTo(object obj)
{

    Land temp = obj as Land;
    if(temp != null)
    { 
        if(Oppervlakte > temp.Oppervlakte) return 1;
        if(Oppervlakte < temp.Oppervlakte) return -1;
        if(this.Inwoners > temp.Inwoners) return 1;
        if(this.Inwoners < temp.Inwoners) return -1;
    }
    else
        throw new ArgumentException("Object is not a Land"); 
    
}
```

Ik laat jou de code schrijven wat er moet gebeuren indien het aantal inwoners én de oppervlakte dezelfde is. Misschien kan je dan sorteren volgens de `Naam` van het land.

{% hint style="info" %}
De bestaande datatypes in .NET hebben allemaal de `IComparable` interface ingebakken. Zo ook dus de gekende primitieve datatypes. `string` dus ook en laat dus toe om bijvoorbeeld snel te weten welke van 2 string alfabetisch eerst komt, als volgt:

```csharp
return this.Naam.CompareTo(temp.Naam);
```

Kortom, voeg dit achteraan de eerder geschreven vergelijkingen in je `Land`-klasse om finaal de `Naam` te gebruiken als sorteer-element.
{% endhint %}

## List sorteren

Indien je een `List<Land>` zou willen sorteren in plaats van een array van `Land` dan kan dit ook. Nog steeds vereisen we dat je klasse de `IComparable` interface gebruikt. We kunnen nu de ingebouwde `Sort`-methode van de `List` klasse gebruiken. Stel dat je een lijst van landen hebt genaamd `landLijst`, deze sorteren kan dan heel eenvoudig als volgt:

```csharp
landLijst.Sort();
```

Zo simpel!

**Merk op dat we hier de lijst zelf sorteren. Er wordt dus geen nieuwe lijst teruggegeven zoals bij `Array.Sort()` het geval is.**

Indien je toch liever `Array.Sort` gebruikt dan kunnen we een andere, handige, ingebouwde `List`-methode gebruiken, namelijk `ToArray()`, als volgt:

```csharp
landLijst = Array.Sort(landLijst.ToArray());
```

[^1]: Zie [https://msdn.microsoft.com/system.icomparable](https://github.com/timdams/ziescherpscherper_gitbook/blob/main/16_interfaces/msdn.microsoft.com/system.icomparable)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://apwt.gitbook.io/zie-scherp-scherper/h17-interfaces/2_interfacesinpraktijk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
