Setting read only on a custom struct containing an hashmap

So, I have the following struct that I get from a system before using it in jobs in other systems:

    public struct SerializedIntMap
    {
        private readonly NativeHashMap<FixedString64, Entity> hashMap;
        private readonly ComponentDataFromEntity<SerializedInt> componentDataFromEntity;

        public SerializedIntMap(NativeHashMap<FixedString64, Entity> hashMap,
            ComponentDataFromEntity<SerializedInt> componentDataFromEntity)
        {
            this.hashMap = hashMap;
            this.componentDataFromEntity = componentDataFromEntity;
        }

        public int GetValue(FixedString64 id)
        {
            if (hashMap.TryGetValue(id, out var entity))
            {
                return componentDataFromEntity[entity].Value;
            }
           
            Debug.LogError($"Can't find SerializedInt named {id}");
            return default;
        }
    }

That I use like that:

var map = mappingSystem.GetIntMap();           

Entities.ForEach((Whatever whatever) =>
    {
        var value = map.GetValue(whatever.Id);
        // Do stuff with value
    }).Schedule();

It works out well, but if I have multiple system scheduling jobs using those, it will output an error because it thinks that I write to the same NativeHashMap (it’s always the same in all SerializedIntMap), even if I only read from it.

Now, I tried to do the following:

Entities.WithReadOnly(serializedIntMap)...

which changes nothing, I guess because SerializedIntMap isn’t considered a NativeCollection, or

var hashMap = serializedIntMap.hashMap;
Entities.WithReadOnly(hashMap)...

Which doesn’t work either because it says that hashMap isn’t used in the Lambda expression (even if it’s used in GetValue calls). Only way I made it work is by explicitely getting hashMap from the , adding it to WithReadOnly and adding it as an argument of GetValue. It works, but it’s not as clean as my previous design.

I guess the best way to do something like this would be to find a way for my SerializedIntMap to be considered a NativeCollection that will contain another NativeCollection (the NativeHashMap), but I’m not sure it’s even possible. I’m not really used to using unsafe, I’m not sure it’s needed in that case too. Anybody has any idea how I could make that work?

You could add [ReadOnly] to the field in the struct

It still doesn’t work, it seems I really need to feed something in a .WithReadOnly() call, and this value needs to be a local variable that is explicitely used in the Lambda expression for it to work without breaking. I guess I really need to make SerializedIntMap a NativeCollection that I can set readonly, but I have no clue how to even start doing that.

All WithOnly() does is add [ReadOnly] to the struct in the codegen. (Make sure it’s the Unity.Collections version not the System.ComponentModel version that pops up in ides)

I make container structs like this all the time and it works fine so if adding that to the field doesn’t work, your issue is elsewhere (what else is reading this hashmap).

Damn, you’re right, I’m dumb, there was another job that was writing to it before that I had to add as a dependency. It really is considered as ReadOnly by using the attribute in the struct, I tried to write to it to be sure and it popped an exception. Thanks!

To add on this, it would seem that using the builtin readonly modifier is enough for the NativeHashMap to be the equivalent of [ReadOnly].