【问题标题】:System.Collections.Generic.KeyNotFoundException : The given key 'Item' was not present in the dictionarySystem.Collections.Generic.KeyNotFoundException:字典中不存在给定键“Item”
【发布时间】:2021-10-18 22:37:30
【问题描述】:

我正在尝试用 C# 实现一个基本的精灵游戏。我正在测试两个字典是否彼此相等,并且我遇到了 Containskey() 以及精灵类中的 Equals 函数的问题。

public class Sprite
{
    private Point p;
    private uint Horiz;
    private uint Vert;
    private uint Health;
    private uint Shield;
    private Dictionary<Item, int> inv;
    private string[] QuickSlots;

    /* Default constructor
     * set all values to 0
     */
    //string[] empty;
    //string [] mt;
    public Sprite()
    {
        Point newpoint = new Point();
        newpoint.SetX(0);
        newpoint.SetY(0);
        newpoint.SetZ(0);
        p = newpoint;
        Horiz = 0;
        Vert = 0;
        Health = 0;
        Shield = 0;
        inv = null;
        QuickSlots = null;
    }

    public override int GetHashCode()
    {
        return (int)(p.GetX() ^ (p.GetY() << 8) ^ (p.GetZ() << 16) ^
            Horiz ^ (Vert << 9) ^ 
            (Health << 18) ^ (Shield << 25));
    }

    public bool DictionaryEquals(Dictionary<Item, int> inv2)
    {
        foreach(KeyValuePair<Item, int> entry in inv2)
        {
            if(inv.ContainsKey(entry.Key)) //(inv[entry.Key] == inv2[entry.Key]))
            {
                if((inv[entry.Key] == inv2[entry.Key]))
                {
                    continue;
                }
                else{
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        return true;
    }

    public override bool Equals(Object obj)
    {
        //Check for null and compare run-time types.
            if ((obj == null) || ! this.GetType().Equals(obj.GetType()))
            {
                return false;
            }
            else 
        {
                Sprite s = (Sprite) obj;
            //   this.PrintInventory();
                s.PrintInventory();
            return 
                ((p.Equals(s.p)) &&
                (inv.Equals(s.inv)) &&
                //(QuickSlots == s.QuickSlots) &&
                (Horiz == s.Horiz) &&
                (Vert == s.Vert) &&
                (Health == s.Health) &&
                (Shield == s.Shield));
            }
    }

    public bool HasItem(string item)
    {
        return inv.ContainsKey(StringtoItem(item, this));
    }

    public void TakeItem(string item)
    {
        Console.WriteLine("Does this even work\n");
        if(HasItem(item))
        {
            Console.WriteLine("Does this even work2\n");
            int x = inv[StringtoItem(item, this)] - 1;
            if(x > 0)
            {
                Console.WriteLine("Does this even work3\n");
                inv[StringtoItem(item, this)] = x;
            }
            else
            {
                Console.WriteLine("Does this even work4\n");
                inv.Remove(StringtoItem(item, this));
            }
        }
    }
}

在这里,dictionary.Equals() 函数正常工作,但我的 testSprite 没有一个与我预期的 Sprite 匹配,因为当我使用一个项目时,它不会从 testSprite 库存中正确减少。 takeItem 函数调用 hasItem 函数来检查字典/库存是否有一个项目,它总是返回 false,因为 containskey 函数总是返回 false,即使我知道在打印出的内容时字典包含键的事实字典到控制台。

下面是 Item.cs 文件。

public class Item
{
        private string name;
        protected Sprite holder;

        public Item(string n, Sprite h)
        //, int hc, int sc, int ec,
        //      uint mh, uint ms, bool i, uint s, uint md)
        {
                name = n;
                holder = h;
        }

        public string GetItemName()
        {
            return name;
        }
   
        public override int GetHashCode()
    {
        return (int)(name.GetHashCode() ^ (holder.GetPoint().GetX() << 8) ^ (holder.GetPoint().GetY() << 16) ^ 
            (holder.GetPoint().GetZ() << 16) ^
            holder.GetHoriz() ^ (holder.GetVert() << 9) ^ 
            (holder.GetHealth() << 18) ^ (holder.GetShield() << 25));
    }




        public override bool Equals(Object obj)
    {
        //Check for null and compare run-time types.
            if ((obj == null) || ! this.GetType().Equals(obj.GetType()))
            {
                return false;
            }
            else 
        {
                Item i = (Item) obj;
            return 
                ((name == i.name) &&
                (holder.Equals(i.holder)));
            }
    }
}

我怀疑 GetHashCode 函数之一有问题,但我不完全确定如何修复它,因此不胜感激。谢谢

【问题讨论】:

    标签: c# dictionary oop


    【解决方案1】:

    == 用于引用相等(对于引用类型,例如 Item 是一个类),但似乎您在这里需要的是结构相等 - 所以 inv[entry.Key] == inv2[entry.Key] 将失败 - 尝试 inv[entry.Key].Equals(inv2[entry.Key]) (你确实覆盖Equals 和 GetHashCode 已经根据您的结构相等逻辑)。 您也可以将public class Item : IEquatable&lt;Item&gt; 作为奖励:)

    【讨论】:

    • 好的,我试试。谢谢
    • 好的,让我知道结果!我建议您也可以编辑问题以包含调用这些类的代码。
    • @blub_9 我已经更正了我的帖子,我之前提到的接口不是强制性的。
    • 我最终在我的 gethashcode 函数中包含了私有字符串名称,这样就消除了错误。不过还是谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-18
    • 2022-09-28
    相关资源
    最近更新 更多