当使用struct作为通用字典键时,为什么C#会生成垃圾?

Xar*_*ugh 6 c# dictionary garbage-collection

我有一个结构的通用字典作为键,一个类引用作为值.

Dictionary<IntVector2, SpriteRenderer> tileRendererMap;
Run Code Online (Sandbox Code Playgroud)

我通过坐标检索对渲染器的引用,并将其更改为:

tileRendererMap[tileCoord].color = Color.cyan;
Run Code Online (Sandbox Code Playgroud)

每次使用它时都会产生0.8KB的垃圾.这是默认行为吗?我认为字典查找将是最有效的事情之一.我需要找到解决方法,因为我正在为移动平台工作,这是一个关键系统.

任何想法我可能做错了或如何获得免配置查找?

更多测试后编辑:

使用int作为键而不是我的自定义结构按预期工作.没有分配,没有问题,我认为使用id作为密钥并不奇怪.但是,对于我的游戏,我想将与特定图块相关联的渲染器存储在网格中,实际上不需要是任何类型的对象,因为我只关心网格位置.因此,我认为IntVector2可能是一个实用的标识符,但如果必须,我可以解决它.

使用我的结构时,我得到了分配,我用Unity3D Profiler测量.它在Dictionary_get_item中报告0.8KB ,特别是DefaultComparer.Equals().显然它是一个装箱/拆箱问题,但即使我实现自定义覆盖,它仍然会产生垃圾,只比以前少一点.

我的基本结构实现:

public struct IntVector2
{
    public int x, y;

    public override bool Equals(object obj)
    {
        if (obj == null || obj is IntVector2 == false)
            return false;

        var data = (IntVector2)obj;
        return x == data.x && y == data.y;
    }

    public override int GetHashCode()
    {
        return x.GetHashCode() ^ y.GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)

接受答案后编辑:

在通用词典中使用时,我的结构的免分配版本.

public struct IntVector2 : IEquatable<IntVector2>
{
    public int x;
    public int y;

    public IntVector2(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public bool Equals(IntVector2 other)
    {
        return x == other.x && y == other.y;
    }
}
Run Code Online (Sandbox Code Playgroud)

词典类使用IEquatable接口,而不是对象覆盖的Equals,这就是为什么我的第一个实现是拳击各为重点搜索时,它检查是否相等时间值之一.

Ser*_*rvy 9

由于您只覆盖Equals并且未实现IEquatable<IntVector2>,因此只要将字典与其中两个实例进行比较,字典就会被强制插入两个实例中的一个,因为它将实例传递给Equals接受的方法object.

如果你实现IEquatable<IntVector2>那么字典可以(并将)使用Equals接受参数的版本作为IntVector2,这将不需要装箱.

  • 这样做了.从profiler消息我推断它是调用常规覆盖Equals,但是使用接口它确实变成了无垃圾调用.正是我所希望的.如果字典键在这种情况下有意义,我仍然应该重新思考. (2认同)