schwammige frage wie immer :)



  • hallo,

    angenommen ich habe folgende klasse.

    class Container
    {
        public int ID;
        public string Name;
        public List<Container> Nodes;
    }
    

    gibt es einen eleganten weg den parent einer instanz zu ermitteln ? ich möchte
    eine methode innerhalb von Container haben, die mir die Container instanz
    zurückgibt, in der meine aufrufende Container Instanz enthalten ist. Dabei
    möchte ich nach möglichkeit die methoden des List Interface erhalten /
    weiternutzen.

    ich könnte natürlich ein private field parentid erstellen und eine methode
    AddNode(Container), die die parentid in den Container schreibt. das suchen des
    parents wäre damit aber immernoch extern und ich müsste auch eine eigen version
    des List Interface basteln.

    Gehts das einfacher ? Vielen Dank für die Antworten und das Lesen 🙂

    edit : nicht ganz unwichtig : ich möchte die klasse später mit dem XMLSerializer
    serialisieren können.


  • Administrator

    Also du möchtest den Container des Containers vom Container im Container des anderen Containers zum Container herausfinden? So hat sich das zumindest angefühlt beim Lesen.

    Dabei nehme ich an, dass du einfach jeweils auf den Elternknoten vom Kindknoten aus zugreifen willst?

    1. NIE NIE NIE NIE NIE NIE NIE Felder öffentlich machen!!!!
    2. Nimm höchstens öffentliche Properties.
    3. Dadurch ist die Liste nicht öffentlich und du kannst deinem Container entsprechende Methoden geben. Dein Container könnte zudem das Interface IEnumerable<Container> implementieren. Dadurch wird er vom XmlSerializer auch direkt als Container erkannt. Wenn du zudem noch eine Methode mit dem Namen Add hinzufügst, wird diese Methode dazu verwendet, um die Knoten wieder hinzuzufügen. Steht alles in der Dokumentation zum XmlSerializer .
    4. Jeder Knoten erhält zudem eine Referenz auf den Elternknoten.
    5. XmlIgnoreAttribute , damit kannst du entsprechende Properties, welche nicht serialisiert werden sollen (z.B. die Referenz auf den Elternknoten) markieren.

    Grüssli



  • Dravere schrieb:

    Also du möchtest den Container des Containers vom Container im Container des anderen Containers zum Container herausfinden?

    Im Container!



  • Dravere schrieb:

    1. NIE NIE NIE NIE NIE NIE NIE Felder öffentlich machen!!!!

    Doch manchmal. Schonmal versucht ein Property per ref oder out an eine Methode zu übergeben? Schonmal versucht mit C++ zu kommunizieren und structs zu übergeben? Schonmal mit zusammengesetzten aber trivialen Wertetypen gearbeitet, die keine Logik benötigen und reine Datensenken sind?

    Dein NIE+ ist gerade ähnlich dogmatisch wie das Geheule im C++-Subforum, was new/delete betrifft. Zu 99.9% wahr, aber nicht die totale Wahrheit 🙂

    .oO(Musste gerade heute einen vector<T> in ein dynamisch alloziertes Array umkopieren und von C++ nach C# zurückgeben. Vielleicht bin ich deshalb etwas empfindlich :D)



  • Teiresias schrieb:

    class Container
    {
        public int ID;
        public string Name;
        public List<Container> Nodes;
    }
    

    gibt es einen eleganten weg den parent einer instanz zu ermitteln ?

    Nein. Nicht ohne weitere Information. Entweder ein Child hat eine Referenz auf das Wurzelobjekt und kann ausgehend davon den Baum absteigen, oder jeder Container muss eine Referenz auf seinen "Parent" haben


  • Administrator

    @μ,
    Ich verfolge die Absicht, einem Anfänger dies einzuhämmern, weil es eben in 99.9% der Fälle korrekt ist. Es soll ihm schlecht werden, wenn er es doch verwenden will und daher mehrere Male überlegen, bevor er es verwendet.

    Du hast zudem ein paar fragwürde Argumente für öffentliche Felder gebracht.

    µ schrieb:

    Schonmal versucht ein Property per ref oder out an eine Methode zu übergeben?

    Das ist definitiv kein Grund ein Feld öffentlich zu machen. Dann nimm lieber eine temporäre Variable!

    µ schrieb:

    Schonmal versucht mit C++ zu kommunizieren und structs zu übergeben?

    Nicht mit C++, aber mit C. Und da musst du ebenfalls nichts öffentlich machen. Deine Variablen im struct dürfen gerne private sein! Und du darfst gerne Properties, Methoden, Konstruktoren, etc. hinzufügen! Das spielt absolut keine Rolle. Daher ebenfalls kein Grund!

    µ schrieb:

    Schonmal mit zusammengesetzten aber trivialen Wertetypen gearbeitet, die keine Logik benötigen und reine Datensenken sind?

    Auch hier empfehle ich dringends Properties zu verwenden. In C++ kann man zum Teil mit diesem Argument noch kommen, da die ganzen Getter und Setter lästig sein können. Aber die Properties in C# machen dies so einfach, dass es absolut keinen Grund gibt, in so einem Fall Felder öffentlich zu machen.

    Ich würde sagen, dass ich mit meinem NIE+ sehr gut liege. Du zeigst schon sehr gut auf, dass du zu unvorsichtig bist und zu schnell Felder öffentlich machst, obwohl es nicht nötig ist. Und sobald sie öffentlich sind, hast du jegliche Kontrolle verloren. Sobald du auch nur ein Log-Eintrag oder ein Debug-Breakpoint beim Schreiben oder Lesen der Variable setzen willst, hast du verloren, wenn dein Feld öffentlich ist.

    Grüssli



  • gott,

    mea culpa, ich hases es selbst wie die pest, wenn der threadersteller nach
    seiner frage in der versenkung verschwindet. habe aber irgendwie im eifer
    des gefechts diesen thread vergessen 🙂

    zum thema : die felder sind natürlich nicht öffentlich, das war nur eine
    vereinfachte form. ich habe das ganze jetzt so gelöst. könnts ja nochmal
    meckern, wenn ihr wollt ;). die klasse selbst wird nie instanziert, sondern
    nur von ihr abgeleitete (mit der etwas schlamperten ausnahme, dass ich einen
    BaseContainer als für den nutzer unsichbaren root knoten missbrauche).

    public class BaseContainer
    	{
    		protected int id = 0;
    		protected bool enabled = true;
    		protected string name = "Root";
    		protected BaseContainer parent = null;
    		protected List<BaseContainer> nodes = new List<BaseContainer>();
    
    		[Category(Constant.CategoryGeneral), DisplayName("Name"), Browsable(true)]
    		public string Name {
    			get { return name; }
    			set { name = value; }
    		}	
    
    		[Category(Constant.CategoryGeneral), DisplayName("ID"), Browsable(false)]
    		public int ID {
    			get { return id; }
    		}
    
    		[Category(Constant.CategoryGeneral), DisplayName("Enabled"), Browsable(true)]
    		public bool Enabled {
    			get { return enabled; }
    			set { enabled = value; }
    		}
    
    		[Browsable(false)]
    		public List<BaseContainer> Nodes {
    			get { return nodes; }
    			set { nodes = value; }
    		}
    
    		[Browsable(false)]
    		public BaseContainer Parent {
    			get { return parent; }
    			set { parent = value; }
    		}
    
    		public void AddChild(BaseContainer Container)
    		{
    			Container.Parent = this;
    			nodes.Add(Container);
    		}
    
    		public bool RemoveChild(int ID)
    		{
    			foreach (BaseContainer bc in nodes) 
    			{
    				if (bc.ID == ID)
    				{
    					nodes.Remove(bc);
    					return true;
    				}
    			}
    			return false;
    		}
    
    		public override string ToString()
    		{
    			bool hasChildren = false;
    
    			if (nodes != null)
    				hasChildren = true;
    			if (parent != null)
    				return string.Format("Name: {0}, ID: {1}, Enabled: {2}, HasChildren: {3}, Parent: {4}", name, id, enabled, hasChildren, parent.ToStringShort());
    			else
    				return string.Format("Name: {0}, ID: {1}, Enabled: {2}, HasChildren: {3}, Parent: Null", name, id, enabled, hasChildren);
    		}
    
    		public string ToStringShort()
    		{
    			return string.Format("{0}(ID: {1})", name, id);
    		}
    
    	}
    

  • Administrator

    1. Hast du meine Vorschläge gelesen?
    2. Hast du die Dokumentation zu XmlSerializer (oben verlinkt) gelesen? Vor allem auch so Dinge, wie oben erwähnt, zu IEnumerable<T> und einer Methode Add ?
    3. Überleg dir mal, was passiert, wenn jemand einen Knoten an mehreren Container hinzufügt.
    4. Überleg dir mal, was passiert, wenn jemand das Parent-Property ändert.
    5. Überleg dir mal, was passiert, wenn jemand einen neuen Container an Nodes zuweist. Haben die darin enthaltenen Knoten den korrekten Parent?
    6. Überleg dir mal, was passiert, wenn du diese Basisklasse serialisierst, wie du es im Eingangsbeitrag als Anforderung drin hast.

    Grüssli



  • -gehört nicht hierhin-



  • Dravere schrieb:

    1. Hast du meine Vorschläge gelesen?
    2. Hast du die Dokumentation zu XmlSerializer (oben verlinkt) gelesen? Vor allem auch so Dinge, wie oben erwähnt, zu IEnumerable<T> und einer Methode Add ?
    3. Überleg dir mal, was passiert, wenn jemand einen Knoten an mehreren Container hinzufügt.
    4. Überleg dir mal, was passiert, wenn jemand das Parent-Property ändert.
    5. Überleg dir mal, was passiert, wenn jemand einen neuen Container an Nodes zuweist. Haben die darin enthaltenen Knoten den korrekten Parent?
    6. Überleg dir mal, was passiert, wenn du diese Basisklasse serialisierst, wie du es im Eingangsbeitrag als Anforderung drin hast.

    Grüssli

    mir fliegt alles um die ohren ? ^^ werde da wohl nochmal ordentlich lesen müssen.
    melde mich zurrück, wenn ich probleme habe 🙂 falls jemand noch lesetipps in die richtung hat, immer her damit .


Anmelden zum Antworten