CS_LEVEL_11_SOLUTION - OnlyCook/abitur-elite-code GitHub Wiki

Level 11 – Musterlösung: Das Klassenzimmer

Lösung

public class Klasse
{
    private string bezeichnung;
    private List<Schueler> schuelerListe;
 
    public Klasse(string bez)
    {
        this.bezeichnung = bez;
        this.schuelerListe = new List<Schueler>();
    }
 
    public void AddSchueler(Schueler s)
    {
        schuelerListe.Add(s);
    }
 
    public double BerechneSchnittBestanden()
    {
        if (schuelerListe.Count == 0) return 0.0;
 
        int bestanden = 0;
        int notenSumme = 0;
 
        foreach (Schueler s in schuelerListe)
        {
            if (s.GetNote() > 4)
            {
                bestanden++;
                notenSumme += s.GetNote();
            }
        }
 
        if (bestanden == 0) return 0.0;
 
        return (double)notenSumme / bestanden;
    }
}
 
public class Schueler
{
    private int note;
 
    public Schueler(int note)
    {
        this.note = note;
    }
 
    public int GetNote()
    {
        return note;
    }
}

Erklärung

Zwei Klassen, eine Beziehung

Dieses Level ist der Einstieg in Sektion 3: Beziehungen & Navigation. Zum ersten Mal implementierst du nicht nur eine Klasse, sondern zwei Klassen, die miteinander zusammenarbeiten: Klasse kennt Schueler – und zwar mehrere davon, gespeichert in einer Liste.

Im UML-Diagramm ist das durch die Assoziation Klasse --> * Schueler ausgedrückt: Eine Klasse hat beliebig viele Schüler.


Die Klasse Schueler

public class Schueler
{
    private int note;
 
    public Schueler(int note)
    {
        this.note = note;
    }
 
    public int GetNote()
    {
        return note;
    }
}

Schueler ist bewusst einfach gehalten – ein einzelnes Attribut, ein Konstruktor, eine Getter-Methode. Das Attribut note ist private, also von außen nicht direkt zugreifbar. Der Zugriff läuft ausschließlich über GetNote(). Das ist das Standard-Muster im Abitur.


Die Klasse Klasse – Konstruktor und Liste

public Klasse(string bez)
{
    this.bezeichnung = bez;
    this.schuelerListe = new List<Schueler>();
}

Wichtig: Die Liste schuelerListe wird im Konstruktor initialisiert – nicht bei der Deklaration. Das ist die im Abitur erwartete Schreibweise. Ohne diese Zeile wäre schuelerListe null, und jeder Aufruf von .Add() würde sofort mit einem Laufzeitfehler scheitern.

AddSchueler(Schueler s) ist die übliche Hilfsmethode, um Objekte von außen in die interne Liste einzutragen.


BerechneSchnittBestanden() – der Kern der Aufgabe

Hier liegt die eigentliche Herausforderung. Die Methode soll den Notendurchschnitt berechnen – aber nur für Schüler, die bestanden haben (Note > 4).

Schritt 1: Leere Liste abfangen

if (schuelerListe.Count == 0) return 0.0;

Bevor irgendetwas berechnet wird, prüfen wir: Gibt es überhaupt Schüler? Wenn nicht, gibt es nichts zu berechnen – direkt 0.0 zurückgeben.

Schritt 2: Zählen und summieren

int bestanden = 0;
int notenSumme = 0;
 
foreach (Schueler s in schuelerListe)
{
    if (s.GetNote() > 4)
    {
        bestanden++;
        notenSumme += s.GetNote();
    }
}

Wir laufen mit einer foreach-Schleife durch alle Schüler. Für jeden Schüler, der bestanden hat (Note strikt größer als 4), erhöhen wir den Zähler bestanden um 1 und addieren seine Note zur Summe. Schüler, die nicht bestanden haben, werden komplett ignoriert.

Warum nicht einfach schuelerListe.Count als Teiler nehmen?
Weil dann auch nicht bestandene Schüler den Durchschnitt beeinflussen würden – das wäre logisch falsch. Wir teilen nur durch die Anzahl der Schüler, die tatsächlich in die Summe eingegangen sind.

Schritt 3: Kein einziger hat bestanden

if (bestanden == 0) return 0.0;

Wenn zwar Schüler vorhanden sind, aber keiner bestanden hat, wäre bestanden == 0. Eine Division durch 0 führt in C# bei int-Division zu einem Laufzeitfehler. Dieser Fall wird daher vorher explizit abgefangen.

Schritt 4: Den Durchschnitt berechnen

return (double)notenSumme / bestanden;

Beide Variablen – notenSumme und bestanden – sind vom Typ int. Eine Division zweier int-Werte ergibt in C# immer ein ganzzahliges Ergebnis (z.B. 7 / 2 = 3, nicht 3.5). Der Cast (double) sorgt dafür, dass die Division als Gleitkommazahl ausgeführt wird und Nachkommastellen erhalten bleiben.


Überblick: Der Ablauf

Schritt Was passiert?
Liste leer? Sofort 0.0 zurückgeben
foreach-Schleife Nur bestandene Schüler zählen und summieren
Niemand bestanden? Sofort 0.0 zurückgeben
Sonst Summe durch Anzahl teilen (mit Cast auf double)
⚠️ **GitHub.com Fallback** ⚠️