List of struct in einer Klasse



  • Hallo,

    Ich kann auf ein Element einer Klasse zwar zugreifen, aber diesen nicht wirklich ändern.

    Ich habe eine Klasse CMesh (es geht um das Element public bool Visible des struct-Elements von CSFamily, welche als Liste in der Klasse CMesh vorhanden ist):

    public unsafe class CMesh
        {
            public List<Struct_cs.CSFamily> IntFamily;
            public List<Struct_cs.CSFamily> ExtFamily;
    
            public bool Visible;
    
            public CMesh()
            {
                IntFamily = new List<Struct_cs.CSFamily>();
                ExtFamily = new List<Struct_cs.CSFamily>();
            }
    
            public CMesh(uint Index)
            {
                IntFamily = new List<Struct_cs.CSFamily>();
                ExtFamily = new List<Struct_cs.CSFamily>();
    
                for (uint fi = 0; fi < Kernel_Interface.nFamilyIntMesh(Index); fi++)
                {
                    IntFamily.Add(new Struct_cs.CSFamily(Marshal.PtrToStringAnsi(Kernel_Interface.FamilyIntNameMesh(Index, fi)), pIntFamily[fi].Index, pIntFamily[fi].P_First, pIntFamily[fi].nElement, true, 255, 255, 255));
                }
                for (uint fi = 0; fi < Kernel_Interface.nFamilyExtMesh(Index); fi++)
                {
                    ExtFamily.Add(new Struct_cs.CSFamily(Marshal.PtrToStringAnsi(Kernel_Interface.FamilyExtNameMesh(Index, fi)), pExtFamily[fi].Index, pExtFamily[fi].P_First, pExtFamily[fi].nElement, true, 255, 255, 255));
                }
            }
    
            ~CMesh()
            {
                Kernel_Interface.DeleteMesh(MeshIndex);
                Visible = false;
            }
        }
    }
    

    Dazu wichtig ist noch die Struct CSFamily, wovon Listen erzeugt werden:

    public struct CSFamily
            {
                public string Name;
                public uint Index;
    
                public TElement* P_First;
                public ulong nElement;
    
                public bool Visible;
    
                public byte Red;
                public byte Green;
                public byte Blue;
    
                public CSFamily(string fName, uint fIndex, TElement* fpElement, ulong fnElement, bool fVisible, byte fRed, byte fGreen, byte fBlue)
                {
                    Name = fName;
                    Index = fIndex;
                    P_First = fpElement;
                    nElement = fnElement;
                    Visible = fVisible;
                    Red = fRed;
                    Green = fGreen;
                    Blue = fBlue;
                }
            }
    

    Der Konstruktor von CMesh funktioniert wunderbar. Es werden vier Familien für ExtFamily und eine für IntFamily von einer C Libliothek übergeben - wie es sein soll.

    Aber jetzt möchte ich diese Werte ändern, in einem TreeView. In diesem TreeView.AfterChecked Handle wird der komplette Pfad des geänderten Feldes zerlegt und dem entsprechend verzweigt. Wenn z.B. der Hacken bei irgend einem Lines Feld rausgenommen wird, sollen alle Elemente in der Liste ExtFamily[i].Visible auf false gesetzt werden, ist der Hacken gesetzt auf true.
    Und das lässt mich der Kompiler nicht machen. Der Fehler taucht in Zeile 24 bei "M.ExtFamily[fi].Visible = node.Checked;" auf. Fehler bedeutet, dass das Program das mit der Bemerkung
    "Fehler 8 Der Rückgabewert 'System.Collections.Generic.List<CSF2D_21050104.Struct_cs.CSFamily>.this[int]' kann nicht geändert werden, da er keine Variable ist."

    Anbei der Code:

    private void MainTree_AfterCheck(object sender, TreeViewEventArgs e)
            {
                if (e.Action == TreeViewAction.ByMouse)
                {
                    TreeNode node = e.Node;
                    Struct_cs.CSFamily F;
    
                    List<string> TreePath = new List<string>(node.FullPath.Split('\\'));
                    switch (TreePath[0])
                    {
                        case "Mesh":
                            if (TreePath.Count > 1)
                            {
                                foreach(CMesh M in _Mesh)
                                {
                                    if (M.Name == TreePath[1])
                                    {
                                        if (TreePath.Count > 2)
                                        {
                                            if (TreePath[2] == "Lines")
                                            {
                                                for (int fi = 0; fi < M.nExtFamily; fi++)
                                                {
                                                    M.ExtFamily[fi].Visible = node.Checked; /*Hier wird ein Kompilerfehler erzeugt!*/
                                                    listBox1.Items.Add(M.ExtFamily[fi].Name + " = " + M.ExtFamily[fi].Visible);
                                                }
                                            }
                                            else if (TreePath[2] == "Shells")
                                            {
                                                for (int fi = 0; fi < M.nIntFamily; fi++)
                                                {
                                                    F = M.IntFamily[fi];
                                                    F.Visible = node.Checked;
                                                    listBox1.Items.Add(F.Name + " = " + F.Visible);
                                                }
                                            }
                                        }
                                        break;
                                    }
                                }
                            }
                            break;
                        case "Family":
                            bool Found = false;
                            if (TreePath.Count > 1)
                            {
                                foreach (CMesh M in _Mesh)
                                {
                                    if (Found == false)
                                    {
                                        for (int fi = 0; fi < M.ExtFamily.Count; fi++)
                                        {
                                            if (TreePath[1] == M.ExtFamily[fi].Name)
                                            {
                                                Found = true;
                                                F = M.ExtFamily[fi];
                                                F.Visible = node.Checked;
                                                listBox1.Items.Add(F.Name + " = " + F.Visible);
                                            }
                                        }
    
                                        if (Found == false)
                                        {
                                            for (int fi = 0; fi < M.IntFamily.Count; fi++)
                                            {
                                                if(TreePath[1] == M.IntFamily[fi].Name)
                                                {
                                                    Found = true;
                                                    F = M.IntFamily[fi];
                                                    F.Visible = node.Checked;
                                                    listBox1.Items.Add(F.Name + " = " + F.Visible);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
    

    Aber ich greife auf eine Liste von CSFamilay Elemente zu und die haben das Element Visible. Wieso kann ich es nicht ändern? Folgendes funktioniert nämlich durchaus:

    Struct_cs.TFamily F;
    F = ExtFamily[fi];
    Console.LriteLine("Name: " + F.Name + "; Visible: " + F.Visible);
    

    Die Ausgabe ist korrekt.

    Interessant ist auch, dass ich kein

    foreach(Struct_cs.CSFamily F in M){}
    

    weil ihm die öffentliche Definition von "GetNumerator" fehlt.



  • Kennst du den Unterschied zwischen Werte- und Referenztypen? Eine Struktur (struct) ist ersteres und daher müßtest du immer zuerst eine Kopie erzeugen, dann das Feld (bzw. die Eigenschaft) ändern und danach wieder neu zuweisen.
    Mach daher aus deiner Struktur einfach eine Klasse (class)...

    PS Und statt deiner ganzen öffentlichen Felder solltest du besser Eigenschaften benutzen (evtl. sogar nur lesend).

    Und bei deinem letzten Code möchtest du wohl eher

    foreach(Struct_cs.CSFamily F in M.IntFamily) {} // bzw. ExtFamily
    

    Möchtest du aber wirklich über CMesh iterieren können, dann mußt du bei der Klasse die Schnittstelle IEnumerable (bzw. zusätzlich noch IEnumerable<T>) implementieren.

    Und dann ist mir noch aufgefallen, daß deine Schleifen nicht gerade elegant programmiert sind (anstatt 'Found' besser entweder mittels break verlassen oder aber in eigene Methode auslagern und per return verlassen).



  • Super, funktioniert 🙂

    Aber noch ohne foreach. Wieso funktioniert das bei meiner Liste List<CMesh> und nicht bei der Liste in der CMesh Klasse?



  • Deine Frage verstehe ich leider nicht. 😕


Log in to reply