简体   繁体   English

modifiy dictionary value作为out参数和引用

[英]modifiy dictionary value as out parameter and reference

I want to create an Entity-Component-System example. 我想创建一个Entity-Component-System示例。 I have components like 我有像这样的组件

internal struct Position : IComponent
{
    public int X { get; set; }
    public int Y { get; set; }
}

and

internal struct Movementspeed : IComponent
{
    public float Value { get; set; }
}

which implement 哪个实施

internal interface IComponent
{
}

When looping through the components I want to find them as fast as possible. 循环遍历组件时,我希望尽可能快地找到它们。 I thought about creating a Dictionary that takes in the components type as key and the component as value. 我想过创建一个Dictionary,它将组件类型作为键,组件作为值。

internal class ComponentCollection
{
    public ComponentCollection()
    {
        components = new Dictionary<Type, object>();
    }

    private Dictionary<Type, object> components;

    public void AddComponent<T>(T component) // add a new component
    {
        Type componentType = typeof(T);
        components.Add(componentType, component as IComponent);
    }

    public void RemoveComponent(Type componentType) // remove the component by type
    {
        components.Remove(componentType);
    }

    public bool TryGetComponent<T>(out T component) // get the specified component
    {
        try
        {
            Type componentType = typeof(T);
            component = (T)components[componentType];
            return true;
        }
        catch (Exception)
        {
            component = default(T);
            return false;
        }
    }
}

There are two problems that come up. 出现了两个问题。

  1. What if someone creates a new MovementspeedComponent using float movementspeed and tries to add it? 如果有人使用float movementspeed movespeed创建一个新的MovementspeedComponent并尝试添加它会怎么样? Having two floats would throw an duplicate key exception. 有两个浮点数会抛出一个重复的键异常。 I could only add custom struct components which implement the IComponent interface to prevent duplicates. 我只能添加实现IComponent接口的自定义struct组件来防止重复。

  2. When I try to modify the components they are not modified by reference 当我尝试修改组件时,它们不会被引用修改

     private static void Main(string[] args) { ComponentCollection components = new ComponentCollection(); components.AddComponent(new Position()); components.AddComponent(new Movementspeed()); if (components.TryGetComponent(out Position fooPosition)) { fooPosition.X++; Console.WriteLine(fooPosition.X); // prints 1 } if (components.TryGetComponent(out Position barPosition)) { Console.WriteLine(barPosition.X); // prints 0 } Console.ReadLine(); } 

Any suggestions? 有什么建议么?

What if someone creates a new MovementspeedComponent using float movementspeed 如果有人使用float movespeed创建一个新的MovementspeedComponent,该怎么办?

Types are good for keys when we have one object/collection per each type otherwise a Dictionary<Type, object> isn't a good fit, key should be unique. 当我们每种类型都有一个对象/集合时类型适用于键,否则Dictionary<Type, object>不合适,key应该是唯一的。

When I try to modify the components they are not modified by reference 当我尝试修改组件时,它们不会被引用修改

Since all of components are struct s this line of code: 由于所有组件都是struct这段代码:

components.TryGetComponent(out Position fooPosition)

Gets a copy of struct that we have in the dictionary. 获取字典中包含的struct 的副本 A quote from C# guide : 来自C#指南的引用:

Structs are copied on assignment. 根据作业复制结构。 When a struct is assigned to a new variable, all the data is copied, and any modification to the new copy does not change the data for the original copy. 将结构分配给新变量时,将复制所有数据,并且对新副本的任何修改都不会更改原始副本的数据。 This is important to remember when working with collections of value types such as Dictionary. 在处理诸如Dictionary之类的值类型集合时,这一点很重要。

What if someone creates a new MovementspeedComponent using float movementspeed and tries to add it? 如果有人使用float movespeed创建一个新的MovementspeedComponent并尝试添加它会怎么样?

I see 2 solutions. 我看到2个解决方案。 Either use classes instead of structs or add some Update method to update struct in dictionary 使用类而不是结构或添加一些Update方法来更新字典中的结构

public void UpdateComponent<T>(T component)
{
    Type componentType = typeof(T);
    components[componentType] = component;
}

Then call this method after you'r done with updating your struct: 然后在完成更新结构后调用此方法:

if (components.TryGetComponent(out Position fooPosition))
{
    fooPosition.X++;
    components.UpdateComponent(fooPosition);
    Console.WriteLine(fooPosition.X); // prints 1
}

If you'll use classes instead of structs your old solution should work. 如果您将使用类而不是结构,那么您的旧解决方案应该可行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM