c# im dritten Anlauf



  • µ schrieb:

    pascal2009 schrieb:

    Bei Version 2 (das ist das, was gewünscht ist) geschieht seltsames:
    Der Datensatz wird der Liste übergeben, und diese zeigt auch den richtigen Wert.

    Dann wird der Datensatz geändert, die Änderungen werden aber nicht der Liste übergeben. Trotzdem zeigt die Liste jetzt den geänderten Text.

    Kurz: In der List werden nur die Referenzen gespeichert. Die sind vergleichbar mit Zeigern aus der C und C++ Welt.
    CL_Konto ist eine Klasse und damit Referenztyp. Wenn Du testweise mal CL_Konto zu einer struct (Wertetyp!) umwandelst, wird Deine Änderung an kontobez sich nicht mehr auf das Objekt in der List auswirken.

    Ich sage damit nicht, dass Du generell alles als structs modellieren sollst. Der von Dir beobachtete Effekt ist oft ein Segen und genau das was man möchte. Erfordert aber etwas umdenken, wenn man von C/C++ kommt.

    Nachtrag: Wie im vorherigen Post schon geschrieben ist string eine Ausnahme. Obwohl eine Klasse, beobachtest Du im ersten Test ein anderes Verhalten als im zweiten. string ist ein "immutable reference type" dem zusätzlich ein wenig Compilermagie beim Zuweisungsoperator spendiert wurde. Um den Unterschied zwischen Referenz- und Wertetypen zu verstehen, solltest Du string vielleicht vorerst mal außer acht lassen, denn das Verhalten dieser Klasse passt absolut nicht zum Rest der C#-Welt.

    Vielen Dank für die schnelle Antwort. Mittlerweile war ich durch Rumprobieren schon auf der Spur, daß die Liste keine Kopien der übergebenen Objekte anlegt (mit einem Adreßverweis auf den neuen Speicher), sondern einfach einen Verweis auf den vorhandenen Speicherbereich des Elements setzt. Da kbuf als Buffer dient, in dem Sinne, das er ständig überschrieben wird zum Lesen und Schreiben, daher also ständig verändert wird und in der Methode auch für Zuweisungen an andere Datentypen (z. B. bei mehreren Listen) verwendet werden könnte, wäre rückwirkend das letzte Element der jeweils letzten Liste beschädigt, und das ist unerwünscht.

    Abhilfe: Also muß man 1. dem Buffer vor jeder neuen Wertzuweisung mit new neuen Speicher zuweisen, und wenn das erledigt ist, nochmal mit new einen neuen Speicherbereich, so daß er sozusagen ins Leere zeigt, dann kann er in der Liste keinen Unsinn anstellen. So ginge es:

    public bool init_Kontenrahmen_version2()
            {
                // Todo: Konten aus Datei auslesen und in Liste ablegen
                List<CL_Konto> kontenliste = new List<CL_Konto>();
    
                CL_Konto kbuf = new CL_Konto();
                kbuf.kontonr = 4900;
                kbuf.kontobez = "Sonstige Kosten";
                kontenliste.Add(kbuf);
    
                kbuf = new CL_Konto(); // ohne das würde nur der erste Buffer wieder überschrieben
                kbuf.kontonr = 4920;
                kbuf.kontobez = "Telefon";
                kontenliste.Add(kbuf);
    
                MessageBox.Show(kontenliste[0].kontobez); //Sonstige Kosten
                MessageBox.Show(kontenliste[1].kontobez); // Telefon
    
                kbuf = new CL_Konto(); // Zeiger vom letzten Element herunternehmen
                kbuf.kontobez = "geändert"; // so daß sich das nicht  auf die Liste auswirkt
    
                MessageBox.Show(kontenliste[0].kontobez); //Sonstige Kosten
                MessageBox.Show(kontenliste[1].kontobez); // Telefon
                return true;
            }
    

    Das erscheint mir aber nicht sehr elegant und außerdem fehleranfällig, wenn man es mal vergessen sollte. So ein Fehler, daß nur ab und zu jeweils das eine oder andere Element beschädigt ist, wäre gar nicht einfach aufzuspüren.

    Vielleicht wär in dem Fall wirklich eine Struct besser.

    Pascal



  • pascal2009 schrieb:

    Abhilfe: Also muß man 1. dem Buffer für jeden neuen Wert mit new neuen Speicher zuweisen, und wenn das erledigt ist, nochmal mit new einen neuen Speicherbereich, dann kann er in der Liste keinen Unsinn anstellen.

    Ja und das ist völlig in Ordnung. Mehrere Objekte erstellst Du mit mehrfachem new.

    pascal2009 schrieb:

    Das erscheint mir aber nicht sehr elegant und außerdem fehleranfällig, wenn man es mal vergißt.

    Vielleicht wär in dem Fall wirklich eine Struct besser.

    Nein! Verfalle jetzt nicht wieder in die C-Denke.

    Du kannst auf kbuf übrigens ganz verzichten.
    Mit entsprechendem Konstruktor:
    kontenliste.Add(new CL_Konto(4920, "Telefon"));
    Oder mit öffentlichen Properties:
    kontenliste.Add(new CL_Konto{ kontonr = 4920, kontobez = "Telefon"});



  • µ schrieb:

    Nein! Verfalle jetzt nicht wieder in die C-Denke.

    Du kannst auf kbuf übrigens ganz verzichten.
    Mit entsprechendem Konstruktor:
    kontenliste.Add(new CL_Konto(4920, "Telefon"));
    Oder mit öffentlichen Properties:
    kontenliste.Add(new CL_Konto{ kontonr = 4920, kontobez = "Telefon"});

    Ja, der Buffer ist C-Denke. Da er auch nicht so funktioniert wie ursprünglich gedacht, lasse ich ihn demnächst weg.

    Dieser Code sieht auch viel eleganter aus. und mehr nach C#;

    Und er ist sicherer, weil man da nichts vergessen kann.

    Pascal

    PS wäre nur die Frage: in C speichere ich mittels des Buffers solche Datensätze binär und brauche ihn natürlich, um die Datei wieder auszulesen (mit sizeof(buffer)). In C# könnte man den Datensatz in String umformen und als Textdatei speichern (und nach dem Auslesen wieder zerlegen), oder man macht das binär vielleicht mit serialize (was wahrscheinlich deutlich einfacher wäre, hab die Funktion aber noch nicht ausgetestet).



  • Serialisierung ist schon das richtige Stichwort. Das geht sowohl Binär als auch in Textform (xml).



  • hustbaer schrieb:

    string dagegen ist ein Value-Type, und der kann direkt in der ArrayList gespeichert werden.

    Bloß ein Schreibfehler, aber nicht dass es noch jemand glaubt: string ist natürlich ein Referenz-Typ.



  • Der Weg zu C# ist schon steinig. Man kann auch nicht immer alles irgendwo googlen. Im Moment geht es trotz googeln an diesem Punkt nicht weiter:

    Es wird eine Liste erstellt List<ClassPerson> mit string Name und int nr und aufgefüllt mit einigen Datensätzen. Diese Liste soll nun von der aufrufenden Methode weiterverarbeitet bzw. benutzt werden, und was ich nicht hinkriege, ist die Zuweisung.

    Wenn List<ClassPerson> als Rückgabewert mit return zurückkommt, und in der aufrufenden Methode eine List<ClassPerson> mit new definiert ist, kann ich mit List1=handle.fuelleListe() = Rückgabewert der Funktion nicht zuweisen, obwohl innerhalb derselben Methode List1=List2 durchaus funktioniert (da aber keinen Sinn macht).

    Übergabe mit ref oder out?

    Vom Praktischen her wäre das Problem in WinForms schon gelöst, da ich z. B. listBox1 mit den Daten aus der Datei füttern und via SelectedItem in der ganzen WinForms-Umgebung problemlos benutzen kann (wenn auch nur im string-Format, also ständig hin- und herverwandeln). Eine Liste mit strukturierten Daten wäre das Gewünschte.

    In Ansi-C wäre es überhaupt kein Problem ... lassen wir das. Das führt hier nicht weiter.

    Mir fehlt im Moment wirklich die zündende Idee. 😮

    Pascal

    PS: Die Ansi-C-Denke (soll bzw. muß ja ausgemerzt werden, aber kleines Beispiel, was ich eigentlich will). Der Code hier ist aus einem laufenden Programm, was ich für die FiBu benutze. Das ist eine dynamische Liste zu Fuß programmiert, die eine Binärdatei einliest, Datenelement ist eine struct, übergeben wird die Startadresse des ersten Elements der Liste (da wäre natürlich List in C# einiges einfacher, wenn man es denn mal verstanden hätte):

    struct s_element *kopiere_datei_in_liste(char *dname)
    {
            struct s_element *listenkopf=NULL;       
            struct s_element *laufzeiger=NULL;
            struct s_bsatz buffer;     
            FILE *bdp;
            bdp=fopen(dname,"rb");
            if (bdp==NULL){meldung("Kann Datei",dname,"nicht oeffnen");return;}
            while (fread(&buffer,sizeof(struct s_bsatz),1,bdp)==1)
            {
               if (listenkopf==NULL){listenkopf=element_anhaengen(listenkopf);laufzeiger=listenkopf;}
               else laufzeiger=element_anhaengen(laufzeiger);
               laufzeiger->data=buffer;
            }                         
          fclose(bdp);  
          return listenkopf;
    }
    

    Element anhängen ist so definiert (im Grunde ist der Code C# und AnsiC irgendwo von der Logik sehr ähnlich, fast schadet es aber von AnsiC nach C#, weil die Ähnlichkeit eben nur oberflächlich ist, wahrscheinlich besser, man würde bei 0 anfangen, jedenfalls Z. B. malloc und new da sticht die Ähnlichkeit ja wirklich ins Auge:

    struct s_element *element_anhaengen(struct s_element *vorgaenger)
    {
        struct s_element *neues;
        neues=malloc(sizeof(struct s_element));
        neues->next=NULL;
        if (vorgaenger==NULL) neues->prev=NULL;
        else {neues->prev=vorgaenger;vorgaenger->next=neues;}
        return neues;
    }
    


  • List<ClassPerson> fuelleListe()
    {
        var list = new List<ClassPerson> ();
        list.Add(new ClassPerson("Name1", 0));
        list.Add(new ClassPerson("Name2", 1));
        return list;
    }
    
    void methodTest()
    {
        List<ClassPerson> list = fuelleListe();
    }
    

    Meinst du so ? 😕



  • DarkShadow44 schrieb:

    List<ClassPerson> fuelleListe()
    {
        var list = new List<ClassPerson> ();
        list.Add(new ClassPerson("Name1", 0));
        list.Add(new ClassPerson("Name2", 1));
        return list;
    }
    
    void methodTest()
    {
        List<ClassPerson> list = fuelleListe();
    }
    

    Meinst du so ? 😕

    Ich probiere... neu ist dabei der Typ var, hatte ich vorher nicht.

    Deinen Code habe ich jetzt so umgesetzt:

    In der Klasse CL_Konten:

    public class CL_Konten
        {
    
            public class CL_Konto
            {
                public int kontonr;
                public string kontobez;
                public double eroeffnung;
                public double abschluss;
                public char art;
            };
    
            public List<CL_Konto> init_Kontenrahmen()
            {
                var kontenliste = new List<CL_Konto>();
                kontenliste.Add(new CL_Konto { kontonr = 4900, kontobez = "Sonstige Kosten" });
                kontenliste.Add(new CL_Konto { kontonr = 4920, kontobez = "Telefon" });
    
                return kontenliste;
            }
    
        }
    

    Aufruf von WinForms Form1:

    public Form1()
            {
    /*
                InitializeComponent();
                DateTime d = DateTime.Now;
                akt_jahr=d.Year;
                akt_monat = d.Month;
                akt_tag = d.Day;
    
                lfd_jahr=akt_jahr;
                label3.Text = lfd_jahr.ToString();
    */  
    
                CL_Konten kn = new CL_Konten();
                List<CL_Konten> list = kn.init_Kontenrahmen();
    
                MessageBox.Show("Beendet");
    
            }
    

    meckert der Compiler: eine implizite Konvertierung ist nicht möglich ... das hat er vorher bei meinen hundert Versuchen auch immer getan. Hab ich was übersehen?

    Pascal

    PS:

    Hier ist die exakte Fehlermeldung:

    Fehler 1 Eine implizite Konvertierung vom Typ "System.Collections.Generic.List<Fibu2014Version1._1.CL_Konten.CL_Konto>" in "System.Collections.Generic.List<Fibu2014Version1._1.CL_Konten>" ist nicht möglich. C:\Users\Chief\Desktop\Programmierung in C#\Fibu2014Version1.1\Fibu2014Version1.1\Form1.cs 32 36 Fibu2014Version1.1



  • CL_Konto != CL_Konten

    Du gibst eine List<CL_Konto> zurück und willst sie einer Referenz auf List<CL_Konten> zuweisen.



  • µ schrieb:

    CL_Konto != CL_Konten

    Du gibst eine List<CL_Konto> zurück und willst sie einer Referenz auf List<CL_Konten> zuweisen.

    Tausendmal probiert, tausendmal ist nix passiert.

    Ich brauche 2 Handles!

    Tatsächlich, so gegen Mitternacht am nächsten Tag, es geht was:

    public Form1()
            {
                InitializeComponent();
    /*
                DateTime d = DateTime.Now;
                akt_jahr=d.Year;
                akt_monat = d.Month;
                akt_tag = d.Day;
    
                lfd_jahr=akt_jahr;
                label3.Text = lfd_jahr.ToString(); */
    
                CL_Konten          k1 = new CL_Konten();         // Handle 1
                CL_Konten.CL_Konto k2 = new CL_Konten.CL_Konto();// Handle 2
    
                List<CL_Konten.CL_Konto> list = k1.init_Kontenrahmen();
                MessageBox.Show(list[0].kontobez);
                MessageBox.Show("Beendet");
    
            }
    

    ............... macht er genau das, was er soll. 🤡

    Soll das einer verstehen!

    Also wenn jemals jemand sagen würde, C# wäre einfach zu verstehen, dann laß ich mich in die nächste Anstalt einliefern .............. ich hab größte Probleme mit der C# Denke. Ohne die WIN Oberfläche wär ich bei Ansi geblieben, aber das ist Historie ... 😉

    Pascal

    PS: bzw. den handle 2 kann man auch knicken, man muß ihn nur gedanklich berücksichtigen. So denken als ob. Also wenn man den rausnimmt und die Liste auf der zweiten Ebene deklariert mit

    List<CL_Konten.CL_Konto> list = k1.init_Kontenrahmen();

    geht es auch ohne ihn. Auf der tieferen Ebene, wo man die Liste kriegt, würde man aber nicht die Methode kriegen, die liegt ja eine Ebene höher.

    Wie auch immer, es funktioniert! Nix verstanden aber Problem gelöst, ist doch auch was. 🤡



  • pascal2009 schrieb:

    Die einzig logische Erklärung dafür wäre, daß die Liste die Elemente gar nicht speichert, sondern lediglich einen Adressoperator auf den Speicherplatz von kbuf enthält.

    Das ist auch genau so. Hängt aber nicht mit der Liste zusammen. Das ist allgemein so wenn man mit Reference Typen arbeitet.

    Sie funktioniert also nicht als Liste, sondern nur als Zeiger. Was mach ich falsch?

    Du hast C# nicht verstanden.
    Bzw. allgemein den Unterschied zwischen Value Typen und Reference Typen.
    Bei Reference Typen (class) gibt's nur so viele Objekte wie oft nur "new" sagt.



  • GPC schrieb:

    hustbaer schrieb:

    string dagegen ist ein Value-Type, und der kann direkt in der ArrayList gespeichert werden.

    Bloß ein Schreibfehler, aber nicht dass es noch jemand glaubt: string ist natürlich ein Referenz-Typ.

    Hab's korrigiert, danke!



  • pascal2009 schrieb:

    Also wenn jemals jemand sagen würde, C# wäre einfach zu verstehen, dann laß ich mich in die nächste Anstalt einliefern .............. ich hab größte Probleme mit der C# Denke.

    Dir fehlen die ganzen Grundlagen (nicht auf C# bezogen, sondern auf die Programmierung allgemein!). Und so setzt du dich hin und willst ne neue Sprache mit "learning by doing" lernen. Irgendwie klar dass das nicht funktioniert.



  • hustbaer schrieb:

    pascal2009 schrieb:

    Also wenn jemals jemand sagen würde, C# wäre einfach zu verstehen, dann laß ich mich in die nächste Anstalt einliefern .............. ich hab größte Probleme mit der C# Denke.

    Dir fehlen die ganzen Grundlagen (nicht auf C# bezogen, sondern auf die Programmierung allgemein!). Und so setzt du dich hin und willst ne neue Sprache mit "learning by doing" lernen. Irgendwie klar dass das nicht funktioniert.

    Ich hab ganz nette Grundlagen in Ansi-C. Das hab ich glaube ich ziemlich gut begriffen, von der Denke. Hätte Ansi-C eine GUI, wär ich gar nicht hier.

    Beim Umstieg auf C#:

    Problem ist die OOP-Denke.
    Davon abgeleitet, die Sichtbarkeit der Methoden und Variablen, das Problem gibt es in C überhaupt so nicht (daß es nämlich der Compiler vorschreibt).
    .NET ist sehr gut, Klasse, aber: mit den tausend Funktionen muß man sich ja erstmal vertraut machen.
    Mit der WinForms und WPF komme ich dagegen überraschend gut zurecht (dank VisualStudio), was ja auch nicht schwierig ist, wovor ich aber zuvor den größten Respekt hatte. Tatsächlich ist WinForms einfacher als die eigentliche Sprache C#.

    Jetzt habe ich mir sogar noch ein zweites Buch gekauft, aber glaub nicht, daß in den Büchern das drin steht, was du brauchst.

    Man muß viel probieren, von daher kommt das (Praxis, ausprobieren). Nur durch Bücherlesen kommt es nicht (Theorie, hat man 5 Minuten später schon vergessen, was wichtig gewesen wäre).

    Also, in Bezug auf meine C# Programmierung:

    Es funktioniert zunehmend so dies und das. Nicht immer, aber immer öfter.

    Und die Hoffnung stirbt zuletzt 😉

    Pascal



  • pascal2009 schrieb:

    Ich hab ganz nette Grundlagen in Ansi-C. Das hab ich glaube ich ziemlich gut begriffen, von der Denke. Hätte Ansi-C eine GUI, wär ich gar nicht hier.

    Ich will ja nicht Dein Weltbild zerstören, aber rate mal in welcher Sprache das WinApi-Interface geschrieben ist.

    Abgesehen davon: Du kriegst hier Hilfe wie Du bemerkst. Trotzdem reicht es langsam mal mit Deinen Tagebucheinträgen. Das interessiert wirklich niemanden. Bleib beim Fachlichen.

    Grüße



  • hustbaer schrieb:

    Das ist auch genau so. Hängt aber nicht mit der Liste zusammen. Das ist allgemein so wenn man mit Reference Typen arbeitet.

    Allgemein ist das gar nicht so und muß auch nicht so sein.

    Wenn du in C mit malloc(sizeof(irgendwas)) einen Zeiger setzt und dem einen Wert zuweist, dann ist der Speicherplatz des neuen Elements nicht identisch mit dem Speicherplatz des zugewiesenen Wertes. Daß List<T> so arbeitet, hätte mich nicht überrascht, wenn malloc() genauso arbeiten würde.

    Ich will hier aber nicht über AnsiC streiten, sondern in C# dazulernen.

    Und ich finde, dazu sind bisher viele gute Beiträge gekommen.

    Pascal



  • pascal2009 schrieb:

    hustbaer schrieb:

    Das ist auch genau so. Hängt aber nicht mit der Liste zusammen. Das ist allgemein so wenn man mit Reference Typen arbeitet.

    Allgemein ist das gar nicht so und muß auch nicht so sein.

    Wenn du in C mit malloc(sizeof(irgendwas)) einen Zeiger setzt und dem einen Wert zuweist, dann ist der Speicherplatz des neuen Elements nicht identisch mit dem Speicherplatz des zugewiesenen Wertes. Daß List<T> so arbeitet, hätte mich nicht überrascht, wenn malloc() genauso arbeiten würde.

    Ich will hier aber nicht über AnsiC streiten, sondern in C# dazulernen.

    Und ich finde, dazu sind bisher viele gute Beiträge gekommen.

    Pascal

    PS: Nochmal meine Programierung in Ansi-C. Liste aus Datei erzeugen. Da kann man sehen, daß es in Ansi-C ganz anders ist als in List<T>. Es ist formal ähnlich, aber von der Logik völlig anders, weil nirgendwo der Speicherplatz von buffer in die Liste rutscht, sondern die Werte für Buffer auf einen neuen Speicherort kopiert werden (das hat mich ja an List<T> so gewundert, daß die immer in Buffer hängenbleibt):

    // ***************************************** PUBLIC nur die Struktur, nicht die Deklarationen
            struct s_element{
                   struct s_element *next;
                   struct s_element *prev;
                   struct s_bsatz data;
                   };
    
    struct s_element *element_anhaengen(struct s_element *vorgaenger)
    {
        struct s_element *neues;
        neues=malloc(sizeof(struct s_element));
        neues->next=NULL;
        if (vorgaenger==NULL) neues->prev=NULL;
        else {neues->prev=vorgaenger;vorgaenger->next=neues;}
        return neues;
    }
    
    struct s_element *kopiere_datei_in_liste(char *dname)
    {
            struct s_element *listenkopf=NULL;       
            struct s_element *laufzeiger=NULL;
            struct s_bsatz buffer;     
            FILE *bdp;
            bdp=fopen(dname,"rb");
            if (bdp==NULL){meldung("Kann Datei",dname,"nicht oeffnen");return;}
            while (fread(&buffer,sizeof(struct s_bsatz),1,bdp)==1)
            {
               if (listenkopf==NULL){listenkopf=element_anhaengen(listenkopf);laufzeiger=listenkopf;}
               else laufzeiger=element_anhaengen(laufzeiger);
               laufzeiger->data=buffer;
            }                         
          fclose(bdp);  
          return listenkopf;
    }
    


  • Psuedocode:

    ListElement element_anhaengen(ListElement vorgaenger) 
    { 
        ListElement neues; 
        neues=new ListElement(); 
        neues.next=NULL; 
        if (vorgaenger==null) neues.prev=null; 
        else {neues.prev=vorgaenger;vorgaenger.next=neues;} 
        return neues; 
    } 
    
    ListElement kopiere_datei_in_liste(string dname) 
    { 
            ListElement listenkopf=null;       
            ListElement laufzeiger=null; 
            ListData buffer;     
            FileStream bdp = new FileStream(dname, FileMode.Open);
            //if (bdp==NULL){meldung("Kann Datei",dname,"nicht oeffnen");return;} 
            while (/*read struct*/) 
            { 
               if (listenkopf==null){listenkopf=element_anhaengen(listenkopf);laufzeiger=listenkopf;} 
               else laufzeiger=element_anhaengen(laufzeiger); 
               laufzeiger.data=buffer; 
            }                         
          bdp.Close();   
          return listenkopf; 
    }
    

    Macht dann genau das gleiche... 🙄

    Es ist formal ähnlich, aber von der Logik völlig anders, weil nirgendwo der Speicherplatz von buffer in die Liste rutscht, sondern die Werte für Buffer auf einen neuen Speicherort kopiert werden (das hat mich ja an List<T> so gewundert, daß die immer in Buffer hängenbleibt)

    Ehrlich gesagt: Keine Ahnnung was du meinst. 😕
    Wieder das Problem mit Value/Referenz-Typen ?



  • DarkShadow44 schrieb:

    Wieder das Problem mit Value/Referenz-Typen ?

    Ich habe viele Verständnisprobleme mit C#. Nur gerade was Value und Reference betrifft, da hab ich außer dem Umgang mit der Notation überhaupt keine.

    Hilft aber nix, wenn man nicht weiß, wie man die Notation setzen muß um den Compiler dazu zu bewegen, das zu tun, was er soll.

    Es wird ein langer Weg.

    Nett, daß ihr mir hier so behilflich seid.

    Pascal

    Nochmal zu List<T>, was mich daran so irritiert hatte.

    List <T> arbeitet folgendermaßen:

    Ein Element wir mit new erzeugt und mit Daten befüllt

    meineListe.Add führt dann dazu, daß die Liste einen Zeiger auf das Element setzt.

    Würde man das Element verändern (neue Daten aus einer Datei einlesen), und mit

    meineListe.Add hinzufügen, wäre folgendes passiert:

    Der Zeiger von meineListe[0] würde auf das Element zeigen, der Zeiger von meineListe[1] aber auch. Also zeigen alle auf dasselbe Element, egal wie oft man die Funktion .Add aufruft. Wir hätten dann sagen wir 1000 Zeiger auf ein und dasselbe Element erstellt, also das Gegenteil einer Liste, nämlich nur Zeiger auf ein Objekt. Da muß man ja erstmal drauf kommen. Man denkt, die Liste packt die Werte irgendwo in neue SPeicherbereiche, das tut sie aber nicht. Ergo ist das Arbeiten mit dem Befüllen eines Wertebereichs und Zuweisung zur Liste kontraproduktiv bzw. dem Vorgang nicht angemessen.

    Die Notation wie von Mü vorgeschlagen ist dafür optimal

    (1) kontenliste.Add(new CL_Konto(4920, "Telefon"));

    (2) kontenliste.Add(new CL_Konto{ kontonr = 4920, kontobez = "Telefon"});

    Wobei zwischen 1 und 2 der Unterschied besteht, daß der erste Code besser schreibbar ist und der zweite besser lesbar. Ich würde mich aber unbedingt für die 2. Variante entscheiden, da nicht auszuschließen ist, daß sich die Zusammensetzung und die Reihenfolge der Felder im Laufe der Programmierung auch mal ändern könnte und dann hätte man ins Klo gegriffen plus daß der Fehler je nachdem gar nicht so leicht auszumachen wäre.



  • Ein wichtiger Tipp: Hör auf in C zu denken. Man liest ständig so in der Art. In C würde ich das so machen und wie mache ich dann genau das in C#?

    Die Vorgehensweise sollte sein: Ich will Sache X machen und jetzt muss ich schauen wie man Sache X in C# macht _ohne_ den Umweg über C zu gehen. Zur Zeit verrennst Du Dich in teilweise abstrusen Lösungsansätzen weil Du nicht von C loslassen kannst.

    Das ist so wie Menschen die versuche Englisch zu sprechen indem sie den Satz erst in Deutsch formulieren und dann Wort für Wort ins Englische übersetzen. Klappt auch nicht.

    Und wie andere schon sagten, Dein Problem ist nicht C#, sondern OOP-Konzepte. Du würdest in die gleichen Probleme bei jeder anderen Sprache inklusive C++ rennen (C++, nicht unter C++ kompiliertes C)


Anmelden zum Antworten