-->

KeyNotFoundException in filled dictionary

2020-02-14 10:40发布

问题:

I am trying to modify value in dictionary, but the compiler throws KeyNotFoundException. I'm sure, I declared that key in dictionary, because I am calling GenerateEmptyChunks() method, which fills dictionary with chunks with key of their position and values are empty for level generator. I've checked debugger and Chunks dictionary object is correctly filled with keys and values. Is it caused by my unworking CompareTo method? If yes, how I have modify CompareTo method to return right values?

public Dictionary<WPoint, WChunk> Chunks = new Dictionary<WPoint, WChunk>();

GenerateEmptyChunks() method:

public void GenerateEmptyChunks(int Xcount, int Ycount)
    {
        for(int x = 0; x <= Xcount; x++)
        {
            for (int y = 0; y <= Ycount; y++)
            {
                this.Chunks.Add(new WPoint(x, y), new WChunk(x, y));
            }
        }
    }

AddBlock() method which is called by level generator for each tile:

public void AddBlock(WPoint location, int data)
    {
        this.Chunks[location.GetChunk()].AddTile(new WTile(location, data));
    }

WChunk object:

public class WChunk
    {
        public int ChunkX;
        public int ChunkY;
        public SortedDictionary<WPoint, WTile> Tiles = new SortedDictionary<WPoint, WTile>();

        public WChunk(int posX, int posY)
        {
            ChunkX = posX;
            ChunkY = posY;
        }

        public void AddTile(WTile tile)
        {
            Tiles.Add(tile.GetLocation(), tile);
        }
    }

WPoint object:

public class WPoint : IComparable
    {
        public float X;
        public float Y;

        public WPoint(float x, float y)
        {
            X = x;
            Y = y;
        }

        public WPoint GetChunk()
        {
            //Oprava pre bloky mensie ako (1,1)
            if (X <= 16 && Y <= 16)
            {
                return new WPoint(0, 0);
            }
            else
            {
                double pX = (double)(X / 16);
                double pY = (double)(Y / 16);
                return new WPoint((int)Math.Floor(pX), (int)Math.Floor(pY));
            }
        }

        public int CompareTo(object obj)
        {
            WPoint point2 = (WPoint)obj;
            if (point2.X == this.X && point2.Y == this.Y)
            {
                return 0;
            }
            else if (point2.X >= this.X && point2.Y >= this.Y)
            {
                return -1;
            }
            else
            {
                return 1;
            }
        }
}

Any ideas why is compiler rejecting keys, when they are in dictionary?

回答1:

Yes. You have not overridden GetHashCode.



回答2:

Dictionary is using the GetHashCode and Equals for key comparisons, so implementing the IComparable interface is not enough. Have a look at this answer, that's exactly what you need.