C
C#3mo ago
cjhowe

Is it possible to use `Span` with a type erased `System.Array` created with `Array.CreateInstance`?

I am working on a C# ECS which stores its components in an archetype which contains an array of arrays. The outer arrays represent the various component types of the ECS (velocity, position), and the inner arrays represent all of the components of that type in the archetype (position 1 with x = 1, position 2 with y = 5). I want to be able to move components between arrays while avoiding copying in cases where it's unnecessary, even when the type is a value type. Ideally, I would be able to get references to items in this array, which I can pass into methods which expect that reference (these will probably be generic). Right now I'm pretty much always using Array.Copy, which doesn't allow me to get references to the array. Is there a way to obtain Spans or references from a type erased Array?
41 Replies
cjhowe
cjhowe3mo ago
I guess an array of references isn't even possible in C#
SpReeD
SpReeD3mo ago
Technically all ref-types are already refed in C#, the ref keyword is a double reference and different to C/C++. Speaking of which and taking an example on a ref-type like string, string is immutable in C# which will and must result in a different pointer address.
SpReeD
SpReeD3mo ago
As seen, the arrays and variables share all the same pointer since they point a variable created before string a = "hello";
string a = "hello";
string b = "foobar";

string[] c = { a, b };
string[] d = { b, a };

string e = c[0];
string f = d[1];
string[] g = { c[0], d[1] };
string a = "hello";
string b = "foobar";

string[] c = { a, b };
string[] d = { b, a };

string e = c[0];
string f = d[1];
string[] g = { c[0], d[1] };
No description
SpReeD
SpReeD3mo ago
If you want to hold the reference wrap it in an ref-type object like a class or record since the pointer of the object won't change but only the one from it's child property. This will not work with a value-type like a struct.
cjhowe
cjhowe3mo ago
The goal is pretty much to be able to return an array of references to structs. I think the wrapper type idea will probably work to get around that
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Basically, you can ask for a reference to a struct to modify its fields, even though it's a value type, because the variable itself is a reference type
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Yeah, I think I might be boxing anyways... Not sure whether Array.CreateInstance actually avoids this
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Because I don't want to box and unbox when I copy between arrays of the same type
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Yes, that's what I'm using Also, I don't know the types of what I'm storing I have a Type[] array that tells me at runtime
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Yeah, new doesn't work when the type is in a Type value unfortunately
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Gist
EntityFamily.cs
GitHub Gist: instantly share code, notes, and snippets.
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Everything is type erased and yet I want to avoid boxing Using generics, ref structs, etc. This has to be fast, pretty much
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Well, it's okay for some operations in this case The adding/removing components is fine to use boxing
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Basically, I'm going to do queries that have to be high performance, that will let you mutate things in place (no adding/removing/moving components)
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Nah, it's System.Array You would only do this for this situation AFAIK
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Is it though? object[] can store different types: [1, "hello", false]
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
Array.CreateInstance(type, 2) can only store instances of type And that's what I want
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
What I'm doing is a little out there, but it's pretty much a high performance parallel ECS. Since I will be running a great deal of queries on a great deal of entities, and I don't want to serialize all mutation, I want to allow in place edits of structs. This should be faster than using a class reference type I think? Yes, that's pretty much unavoidable. I don't know component types in advanced
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
I don't think so Like, think of it this way: even if I know all combinations of components at compile time that are used with my functions, you can add two different sets of components to the same entity. So this means I can't determine the actual types an entity might have until runtime
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
In the future I will likely need to use something lower level than arrays... I don't know if such a thing exists yet
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
MODiX
MODiX3mo ago
TeBeCo
it's basically object[]
React with ❌ to remove this embed.
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
cjhowe
cjhowe3mo ago
BTW, this is like the 3rd or 4th language I've written this code in; it's definitely possible in C++. But not sure storing managed objects in unmanaged C++ memory is a great idea
Unknown User
Unknown User3mo ago
Message Not Public
Sign In & Join Server To View
SpReeD
SpReeD3mo ago
Definitely something for #allow-unsafe-blocks 🙂 This IEnumerable<IEnumerable<object>> is enough to give me creeps, only dynamic could make it more frightening to me 🙂