C
C#11mo ago
Ham_sandwich

✅ putting an object from an array into a variable changes the array

I'm trying to make a game using Raylib and I have a readonly array with a some levels in it I also have a variable called currentLevel which has levels[0] in it if I do
currentLevel.blocks.RemoveAt(0);
currentLevel.blocks.RemoveAt(0);
it doesn't only remove the first block from currentLevel it also removes it from levels[0]
26 Replies
Aaron
Aaron11mo ago
that's just a feature of reference types (classes), a variable just holds a reference to the actual data, not the data itself, so a copied variable still uses the original data if you want it to not do that, when setting currentLevel, you have to make copies of all the original data yourself
Ham_sandwich
Ham_sandwich11mo ago
How do I make an exact copy of a class without having to enter all the info manually
Angius
Angius11mo ago
Using some deep clone library would probably be the easiest
Ham_sandwich
Ham_sandwich11mo ago
so you can't just make a direct copy with pure .net?
Angius
Angius11mo ago
Not for reference types, no Well, I guess you could do the classic
var newThing = JsonSerializer.Deserialize<Thing>(JsonSerializer.Serialize(oldThing));
var newThing = JsonSerializer.Deserialize<Thing>(JsonSerializer.Serialize(oldThing));
Ham_sandwich
Ham_sandwich11mo ago
how should I reset a level when the player dies then?
Angius
Angius11mo ago
Could maybe try using records They're immutable, so you will always have to create a copy when changing it's values And making a copy should be as simple as with {}
Aaron
Aaron11mo ago
shadow copies though
MODiX
MODiX11mo ago
Angius
REPL Result: Success
record Foo(int Num);
var a = new Foo(69);
var b = a with {};
var c = b with { Num = 420 };

new {a, b, c}
record Foo(int Num);
var a = new Foo(69);
var b = a with {};
var c = b with { Num = 420 };

new {a, b, c}
Result: <>f__AnonymousType0#1<Foo, Foo, Foo>
{
"a": {
"num": 69
},
"b": {
"num": 69
},
"c": {
"num": 420
}
}
{
"a": {
"num": 69
},
"b": {
"num": 69
},
"c": {
"num": 420
}
}
Compile: 565.842ms | Execution: 107.002ms | React with ❌ to remove this embed.
Aaron
Aaron11mo ago
in the example they were using RemoveAt on a list
Angius
Angius11mo ago
Huh, true
Aaron
Aaron11mo ago
would need to swap the list out for like, ImmutableList, then it can work
Ham_sandwich
Ham_sandwich11mo ago
so like this?
c public static readonly ImmutableArray<World> levels = new ImmutableArray<World>{world, world2};
c public static readonly ImmutableArray<World> levels = new ImmutableArray<World>{world, world2};
Angius
Angius11mo ago
More like the list of blocks would have to me immutable And then you could do
thing.TheList = thing.TheList.Skip(1).ToList();
thing.TheList = thing.TheList.Skip(1).ToList();
Although... I think that already clones the list
Ham_sandwich
Ham_sandwich11mo ago
oh wait I have an idea I'm confused
Angius
Angius11mo ago
Just throwing some possibilities for cloning All in all, I'd say your best bet would be to just find some deep clone library, preferably one based on source generators, and just clone your current level or whatever it is
Ham_sandwich
Ham_sandwich11mo ago
but when I do this I get 5 not 2, so why isn't this a reference
Angius
Angius11mo ago
Because integer isn't a reference type It's a value type
Ham_sandwich
Ham_sandwich11mo ago
so what is the reference type when I do
world = levels[0];
world = levels[0];
Angius
Angius11mo ago
Whatever is based on a class is a reference type Whatever is based on a struct is a value type
Ham_sandwich
Ham_sandwich11mo ago
ahhh ok so is there really no easy way to load levels then?
Angius
Angius11mo ago
Deep clone the level from the list into currentLevel
Angius
Angius11mo ago
GitHub
GitHub - mostmand/Cloneable: Auto generate Clone method using C# So...
Auto generate Clone method using C# Source Generator - GitHub - mostmand/Cloneable: Auto generate Clone method using C# Source Generator
Angius
Angius11mo ago
Here, this looks promising
Ham_sandwich
Ham_sandwich11mo ago
thanks a lot for your help
Accord
Accord11mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.