Ein Struct als Parameter gibt nur eine flache Kopie ab?



  • Hallo Leute!

    Ich habe hier ein kleines Problem in meinem Projekt. Es geht grob darum auf ein Array von Objekten zuzugreifen. Dieses Array habe ich in einem struct ausgelagert - und dieses struct übergabe ich dem CTOR meiner Klasse welche auf dieses Array zugreifen möchte.

    Hier das Struct

    struct LevelContext
    	{
    		public ResourceManager<Texture, TextureID> Resource;
    		public GameObject[] InteractableObjects;
    
    		public LevelContext(ResourceManager<Texture, TextureID> resource, GameObject[] interactableObjects)
    		{
    			Resource = resource;
    			InteractableObjects = interactableObjects;
    		}
    	}
    

    Hier wird das Struct als Parameter übergeben:

    protected override void LoadGameObjects()
    		{
    			_player = new GameActor(100, 80, ActorType.Player, _levelContext);
    			_bottom = new SceneObject(SceneObjectType.Bottom, _levelContext);
    		}
    

    Und hier verarbeitet der CTOR die Argumente:

    private GameObject[] _interactableObjects;
    
    //Andere Felder
    
    public GameActor(Int16 health, Int16 speed, ActorType type, LevelContext levelContext)
    		{
    			//Andere
    
    			_interactableObjects = levelContext.InteractableObjects;
    
    			//Andere
    		}
    

    Ich hätte nun gerne gesehen das in meiner GameActor-Klasse, ich eine Referenz zu dem Ursprungs Array von interactableObjects besitze. So dass ich auch im Loop stetig neu in das Array erscheinende Objekte warnehmen kann.

    Das debuggen zeigt mir jedoch das, dass Array nach einigen hundert Loops immernoch leer ist. Somit habe ich wohl nur die Kopie des ersten states des Array bekommen, wo natürlich noch nichts drin war.

    Ich weiss soviel das ein Struct keine Referenz auf sich übergibt sondern eine Kopie, da es ein Wertetyp ist. Jedoch wusste ich nicht, dass die ReferenzTypen ihren Inhalt kopieren. Ich dachte ich bekomme eine Kopie des Pointers mit der Kopie des Structs mit. Somit hätte ich ja immernoch eine valide Referenz auf das ursprüngliche Array und somit auch Zugriff auf jüngste Ereignisse in diesem Array.

    Bitte klärt mich auf - ich bin wieder matschig im Kopf 😞

    gruß Charlie



  • Hallo,

    ich sehe kein Problem. Ich habe das mal Grundlegend nachgebaut und bei mir wird alles korrekt ausgeführt. - Neue Einträge werden ausgegeben.

    Also so fern du C# verwendest, ist irgendwas noch nicht ganz Klar an deinem Vorgehen.

    Folgendes habe ich gemacht um zu versuchen das von dir beschriebene Verhalten zu prüfen:

    Main:

    static void Main(string[] args)
            {
                GameObject[] objects = new GameObject[10];
                LevelContext context = new LevelContext(objects);
                ContextContainer container = new ContextContainer(context);
                for (int i = 0; i < 5; i++)
                {
                    GameObject gObject = new GameObject();
                    gObject.Name = "Item" + i;
                    if (i % 2 == 0)
                        gObject.Color = ConsoleColor.Green;
                    else
                        gObject.Color = ConsoleColor.Red;
    
                    objects[i] = gObject;
                }
    
                container.PrintObjects();
    
                for (int i = 5; i < 10; i++)
                {
                    GameObject gObject = new GameObject();
                    gObject.Name = "Item" + i;
                    if (i % 2 == 0)
                        gObject.Color = ConsoleColor.Green;
                    else
                        gObject.Color = ConsoleColor.Red;
    
                    objects[i] = gObject;
                }
    
                container.PrintObjects();
    
                Console.Read();
            }
        }
    

    ContextContainer:

    struct ContextContainer
        {
            GameObject[] _gameObjects;
    
            public ContextContainer(LevelContext context)
            {
                _gameObjects = context.GameObjects;
            }
    
            public void PrintObjects()
            {
                foreach (GameObject gObject in this._gameObjects)
                {
                    Console.ForegroundColor = gObject.Color;
                    Console.WriteLine(gObject.Name);
                }
            }
        }
    

    LevelContext:

    struct LevelContext
        {
            public GameObject[] GameObjects;
    
            public LevelContext(GameObject[] gameObjects)
            {
                this.GameObjects = gameObjects;
            }
        }
    

    GameObject:

    struct GameObject
        {
            private string _sName;
            public string Name
            {
                get { return _sName; }
                set { _sName = value; }
            }
    
            private ConsoleColor _color;
            public ConsoleColor Color
            {
                get { return _color; }
                set { _color = value; }
            }        
        }
    

    Und selbst wenn ich "GameObject" zu einer Klasse mache, funktioniert es noch immer wie ich es auch gedacht hätte.



  • Hm merkwürdig. Dann muss ich nochmals Debuggen - habe vll. was übersehen oder falsch interpretiert. Ich melde mich falls es immernoch nicht hinhaut!

    Danke für die Mühe mit dem Nachbau!

    Charlie


Anmelden zum Antworten