C# Frage zu "This-Schlüsselwort" Binäre Assoziation

Griffindor01

Cadet 3rd Year
Registriert
Feb. 2021
Beiträge
33
Hallo liebe Gemeinde,

Habe hier gerade ein Programm vorliegen (geht wohl um Beziehungen zwischen Klassen bzw. die binäre Assoziation) und probiere, den Code nachzuvollziehen.
An einer Stelle komme ich jedoch gerade ins stocken. Es geht um den Ausdruck "a.Kunde = this;".

Da das alleine jetzt wohl nicht gerade aussagekräftig ist, füge ich euch untendrunter den Code ein.
Grob geht es um Kunden, welche Aufträge an ein Unternehmen erstellen.

Meine Überlegungen bisher: Nicht jeder Kunde muss denke ich nicht zwangsläufig einen Auftrag erstellen, jeder Auftrag ist aber zwangsläufig einem Kunden zugeordnet. So erkläre ich mir dass es "a.Kunde" und nicht "Kunde.a" heißt.
Was ich mir dann überlegt habe ist, dass durch das "a.Kunde = this" dem Auftrag (durch den Parameter a der Methode übergeben) nun durch das "this" das Kunden-Objekt übermittelt wird, in welchem die Methode "neuerAuftrag" ausgeführt wurde, da bin ich mir aber echt nicht sicher. Soweit mein Ansatz.

Ich kann mir jedoch nach meiner Logik nicht wirklich erklären, wieso das von Nöten ist und nicht einfach das sich darunter befindende "aufträge.Add(a);" ausreicht.

Ich denke, ich habe irgendwo einen Denkfehler. Eure Hilfe schätze ich sehr.

Grüße

Griffindor01


C#:
namespace Binäre_Assoziation
{
    class Program
    {
        static void Main(string[] args)
        {
            //Erzeugen von drei Kunden
            Kunde k1 = new Kunde("Müller");  // 3 Kunden-Objekte werden erstellt, Namen übergeben
            Kunde k2 = new Kunde("Jansen"); // Kunde kann Aufträge erstellen, löschen und ausgeben lassen
            Kunde k3 = new Kunde("Jaust");// Nutzt also Klasse Aufträge, binäre Assoziation


            // Erzeugen von 5 Aufträgen und Eintragen
            // bei den Kunden
            k1.neuerAuftrag( new Auftrag(1) ); // Methode neuerAuftrag wird bei bestimmtem Kunden-Objekt verwendet, ihm wird Objekt Auftrag übergeben
            k2.neuerAuftrag( new Auftrag(2) );
            k3.neuerAuftrag( new Auftrag(3) );
            k1.neuerAuftrag( new Auftrag(4) );
            k3.neuerAuftrag( new Auftrag(5) );
          

            zeigeAlleKundenAuftraege(k1);
            zeigeAlleKundenAuftraege(k2);
            zeigeAlleKundenAuftraege(k3);

            // Aufträge löschen
            k1.loescheAuftrag(0);
            k3.loescheAuftrag(0);

            // Neuen Auftrag anlegen
            k3.neuerAuftrag(new Auftrag(6));

            zeigeAlleKundenAuftraege(k1);
            zeigeAlleKundenAuftraege(k2);
            zeigeAlleKundenAuftraege(k3);

            // Auftragsdaten holen
            Auftrag a = k2.holeAuftrag(1);
            if ( a!= null)
                Console.WriteLine("Kunde {0}: Auftrag {1}",
                        a.Kunde.Name, a.Auftragsnummer);
            else
                Console.WriteLine("Auftrag existiert nicht\n");

            // Auftrag holen und anderem Kunden zuordnen
            Auftrag a_alt = k2.holeAuftrag(0);
            if ( a_alt != null )
            {
                // Nun Kunde k1 zuordnen
                k1.neuerAuftrag(a_alt);
                // Und beim alten Kunden löschen
                k2.loescheAuftrag(0);
            }
            else
                Console.WriteLine("Auftrag existiert nicht");

            zeigeAlleKundenAuftraege(k1);
            zeigeAlleKundenAuftraege(k2);
            zeigeAlleKundenAuftraege(k3);
        
        }

        static void zeigeAlleKundenAuftraege(Kunde k)
        {
            // Aufträge der Kunden ausgeben
            foreach (Auftrag a in k.Aufträge)
            {
                Console.WriteLine("Kunde {0}: Auftrag {1}",
                        a.Kunde.Name, a.Auftragsnummer);
            }
            Console.ReadLine();
        }
      
      
    }
}



















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

namespace Binäre_Assoziation
{
    class Kunde
    {
        // Private Felder/Attribute
        private string name;
        private List<Auftrag> aufträge;

        // Properties für den Zugriff
        // auf die Felder/Attribute
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public List<Auftrag> Aufträge
        {
            get { return aufträge; }
        }

        public Kunde(string n)
        {
            name = n;
            aufträge = new List<Auftrag>();
        }

        public void neuerAuftrag(Auftrag a)
        {
            // Auftrag a dem Kunden zuordnen
            a.Kunde = this;
            aufträge.Add(a);
        }
        public void loescheAuftrag(int anr)
        {
            // Auftrag anhand der Auftragsnummer anr löschen
            if (anr >= 0 && anr < aufträge.Count)
                aufträge.RemoveAt(anr);
        }
        public Auftrag holeAuftrag(int anr)
        {
            // Auftragsdaten anhand der Auftragsnummer anr ermitteln
            if (anr >= 0 && anr < aufträge.Count)
                return aufträge[anr];
            else
                return null;
        }
      
    }
}





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

namespace Binäre_Assoziation
{
    class Auftrag
    {
        // Private Felder/Attribute
        private int  auftragsnummer;
        Kunde auftragnehmer;

        public int Auftragsnummer
        {
            get { return auftragsnummer; }
            set { auftragsnummer = value; }
        }

        public Kunde Kunde
        {
            // Liefert Kunden-Objekt
            get { return auftragnehmer; }
            // Setzt oder löscht Kunden-Objekt
            set { auftragnehmer = value; }
        }

        public Auftrag(int anr)
        {
            auftragsnummer = anr;
        }
    }
}
 
Zuletzt bearbeitet:
Sei bitte so gut und nutze für den Code den Code-Tag, damit ist der Code lesbar
 
  • Gefällt mir
Reaktionen: Griffindor01 und Physikbuddha
Das ist eine Übungsaufgabe, oder? Sieht mir arg verklausuliert und unnötig komplex aus... 🤔
Griffindor01 schrieb:
Was ich mir dann überlegt habe ist, dass durch das "a.Kunde = this" dem Auftrag (durch den Parameter a der Methode übergeben) nun durch das "this" das Kunden-Objekt übermittelt wird, in welchem die Methode "neuerAuftrag" ausgeführt wurde,

Das ist schon mal der richtige Ansatz.
Konkret warum das so gemacht wurde, das mußt Du wohl den Ersteller des Programms fragen. Hier sind wir beim Objektmodell, wo es - wie Du ja erkannt hast -- erstmal darum geht, wer mit wem wie interagieren können soll und muß.

Ich ganz persönlich halte die wechselseitige Verknüpfung von Kunde und Auftrag für gefährlich und würde sowas dringend vermeiden wollen, aber ich bin auch nicht der Ersteller - gottseidank :daumen:
 
breedmaster schrieb:
Sei bitte so gut und nutze für den Code den Code-Tag, damit ist der Code lesbar
erledigt
Ergänzung ()

RalphS schrieb:
Das ist eine Übungsaufgabe, oder? Sieht mir arg verklausuliert und unnötig komplex aus... 🤔


Das ist schon mal der richtige Ansatz.
Konkret warum das so gemacht wurde, das mußt Du wohl den Ersteller des Programms fragen. Hier sind wir beim Objektmodell, wo es - wie Du ja erkannt hast -- erstmal darum geht, wer mit wem wie interagieren können soll und muß.

Ich ganz persönlich halte die wechselseitige Verknüpfung von Kunde und Auftrag für gefährlich und würde sowas dringend vermeiden wollen, aber ich bin auch nicht der Ersteller - gottseidank :daumen:
Okay, danke dir
 
Zuletzt bearbeitet:
C#:
public void loescheAuftrag(int anr)
        {
            // Auftrag anhand der Auftragsnummer anr löschen
            if (anr >= 0 && anr < aufträge.Count)
                aufträge.RemoveAt(anr);

Hier habe ich erneut eine Frage ...
Ich verstehe die Bedingung zum löschen hier nicht.
Im Beispiel werden 5 Aufträge (Mit den Zahlen 1-5 erstellt).

Nun der erste Ausdruck:
Wenn die Auftragsnummer größer oder gleich dem Wert 0 entspricht und ein weiteres Kriterium erfüllt ist,
kann ich es löschen. Soweit noch recht verständlich, wobei eine Auftragsnummer 0 eigentlich recht wenig Sinn macht und im Beispiel ja auch nicht enthalten ist, man würde doch bei Auftragsnummern bei 1 Anfangen zu zählen.

Nun der zweite Ausdruck:
Wenn das erste Kriterium (Dass der Wert größer oder gleich 0 ist) erfüllt ist und die Auftragsnummer kleiner als die Anzahl der Listenelemente ist, kann die Auftragsnummer gelöscht werden.

Das verstehe ich überhaupt nicht. In Listen findet man doch den nullbasierten Index vor, also es wird von null angefangen zu zählen. Im Beispiel vom Code, bei dem es die Auftragsnummern 1-5 gibt, würden diese doch dann den Stellen 0-4 in der Liste entsprechen. Das beeinflusst denke ich erstmal nicht den Count-Befehl (Der sollte 5 Elemente zählen), aber dann wird doch durch das RemoveAt ein falsches Element gelöscht?!

Wenn ich beispielhaft die Auftragsnummer 3 löschen mag, wird nach meinem Verständnis folgendes abgefragt:

Ist die Zahl 3 größer oder gleich 0 ? - JA
Ist die Zahl 3 kleiner als die Anzahl der Listenelemente (5) - JA

Lösche das dritte Element der Liste [1 2 3 4 5] - In diesem Fall dann die 4, wenn man von 0 startet

Ebenfalls wenn ich die Auftragsnummer 5 löschen wollen würde, hätte diese doch nicht einen kleineren Wert als die Gesamtelemente der Liste und das würde nicht funktionieren ...

Das kann doch so nicht stimmen, wo ist da mein Denkfehler? Oder wurde tatsächlich falsch vom Lehrer programmiert?!
 
Zuletzt bearbeitet:
Griffindor01 schrieb:
Das kann doch so nicht stimmen, wo ist da mein Denkfehler? Oder wurde tatsächlich falsch vom Lehrer programmiert?!

Ja, der Lehrer hat da schlecht programmiert und du bist zurecht ins stutzen gekommen. Er setzt die ID des Auftrags mit dem Index in der Liste gleich. Eine Liste hat jeweils eine Methode zum löschen eines Element anhand des Indexes: "RemoveAt()" und eine mit der du das Element selbst auswählen kannst: "Remove()"
Damit kann man dann auch sowas machen:
C#:
List<int> list = new List<int>();
list.Add(465226);
list.Remove(465226);
Sollte das Element nicht in der List sein, so ist dies kein Problem. Du kannst natürlich vorher abfragen, ob das Element existiert mit "Contains()". Und ggf. eine Meldung anzeigen lassen.

Auch wenn es hier natürlich um einfache Beispiele geht, so ist der Code insgesamt schlecht. Angefangen damit, dass deutsche Variablen Namen verwendet werden. Solltest du Interesse haben selbst weiter programmieren zu lernen, dann schau dir da bloß nichts von ab.
 
breedmaster schrieb:
Danke schonmal, aber wieso funktioniert das Programm dann tadellos? Auch wenn es schlecht programmiert wurde, würde ich gerne wissen, wie das dennoch funktioniert, also wie die ID des Auftrags mit dem Index der Liste gleichgesetzt wurde. Wenn es ebenso immer den Auftrag 0 gäbe, würde das ganze nach meinem Verständnis funktionieren (Habe die IDs 0-5, aber 6 Elemente in der Liste, daher muss die ID immer kleiner als die Elemente der Liste sein). Im Programm wurden jedoch eigentlich nur die IDs zwischen 1-5 den Kunden zugewiesen. Andererseits steht dann im Code:

k1.loescheAuftrag(0);

Obwohl dem Kunden 1 vorher gar kein Auftrag 0 zugewiesen wurde. Passiert das automatisch? Wenn ja, wieso?
Ergänzung ()

Griffindor01 schrieb:
Verstehe, mit dem loescheAuftrag(0) wird nicht der Auftrag 0 (den es nicht gibt), sondern der Auftrag an Inden-Stelle 0 der Liste gelöscht. Das habe ich jetzt, als ich mir das nochmal angeschaut habe, verstanden.

Aber wie sieht es mit meiner Anfangsfrage zu diesem Stück Code aus?

C#:
public void loescheAuftrag(int anr)
        {
            // Auftrag anhand der Auftragsnummer anr löschen
            if (anr >= 0 && anr < aufträge.Count)
                aufträge.RemoveAt(anr);
]
 
Zuletzt bearbeitet von einem Moderator:
Code:
loescheAuftrag(0);
löscht immer den ersten Auftrag in der Liste. Exception, wenn kein Element vorhanden ist. Welche Auftragsnummer vergeben wurde ist irrelevant.

Bau/Ersetze das mal ein:
C#:
public void loescheAuftrag(int anr)
{
    // Auftrag anhand der Auftragsnummer anr löschen
    if (anr >= 0 && anr < aufträge.Count)
    {
        Console.WriteLine($"Lösche Auftrag mit Auftragsnummer:{aufträge[anr].Auftragsnummer} und Index:{anr}") ;
        aufträge.RemoveAt(anr);
    }
}

Benutze unbedingt(!) den Debugger.
 
Griffindor01 schrieb:
breedmaster schrieb:
Alles klar, habe jetzt denke ich verstanden, was mein Denkfehler war.
Ist echt missverständlich von meinem Lehrer gecodet worden, wie ich finde.

Bei den Methoden "loescheAuftrag" und "holeAuftrag" wird der Auftrag mit dem entsprechenden Index, den man der Methode übergibt ausgegeben. Also übergibt man den Methoden nicht den Auftrag, sondern den Index. Jetzt habe ich es verstanden.

Danke für deinen Schnipsel Code, so ist das definitiv verständlicher geschrieben.

Kurze Frage, was ist mit dem "Debugger" denn genau gemeint (bitte recht einfach halten, bin noch ein Anfänger).
Hier hieß es nämlich in der Übungs-PDF "führen Sie es „ohne Debugging“ aus."
Dachte bisher immer, das Debugging sei einfach der Vorgang, indem der Code gelesen, auf Fehler überprüft und dann wenn alles passt ausgegeben wird?
Liege ich da falsch?



Dann hätten sich meine Fragen erstmal erledigt

Großes Dankeschön
 
Zuletzt bearbeitet von einem Moderator:
Griffindor01 schrieb:
Ist echt missverständlich von meinem Lehrer gecodet worden, wie ich finde.
Nein, sogar falsch. Es wird so getan, als ob man die Auftragsnummer nutzen kann.
Griffindor01 schrieb:
Kurze Frage, was ist mit dem "Debugger" denn genau gemeint (bitte recht einfach halten, bin noch ein Anfänger).
Hier hieß es nämlich in der Übungs-PDF "führen Sie es „ohne Debugging“ aus."
Dachte bisher immer, das Debugging sei einfach der Vorgang, indem der Code gelesen, auf Fehler überprüft und dann wenn alles passt ausgegeben wird?
Liege ich da falsch?
Mit dem Debugger kannst du verfolgen was Schritt für Schritt im Code passiert. Du kannst an beliebiger Stelle einen Haltepunkt setzten und z.B. schauen, wie die Liste gerade aussieht. Dies ist essentiell um den Verlauf eines Programm nachvollziehen zu können und evtl. Fehler zu entdecken. Deine Erklärung passt da auch schon.
Screenshot 2021-04-12 165234.png
Solltest du Visual Studio einsetzen hier mal in Ruhe lesen:
https://docs.microsoft.com/de-de/visualstudio/debugger/debugger-feature-tour?view=vs-2019

Allgemein zum Aufbau:
Die Aufträge sollten in einer Liste unabhängig vom Kunden gespeichert werden. Ein Kundenobjekt bekommt als Property eine KundenID. Löscht man in dem jetzigen Zustand einen Kunden, so löscht man den Auftrag mit.
Will man jetzt alle Aufträge sehen, so muss man alle Kunden durchgehen.
Griffindor01 schrieb:
Großes Dankeschön
Gerne
 
Zurück
Oben