KeyNot Найдено исключение в словаре (из T)
Я почти готов биться головой об стену
У меня есть класс с именем Map, в котором есть словарь, который называется плитки.
class Map
{
public Dictionary<Location, Tile> tiles = new Dictionary<Location, Tile>();
public Size mapSize;
public Map(Size size)
{
this.mapSize = size;
}
//etc...
Я временно заполняю этот словарь, чтобы проверить некоторые вещи..
public void FillTemp(Dictionary<int, Item> itemInfo)
{
Random r = new Random();
for(int i =0; i < mapSize.Width; i++)
{
for(int j=0; j<mapSize.Height; j++)
{
Location temp = new Location(i, j, 0);
int rint = r.Next(0, (itemInfo.Count - 1));
Tile t = new Tile(new Item(rint, rint));
tiles[temp] = t;
}
}
}
и в моей основной программный код
Map m = new Map(10, 10);
m.FillTemp(iInfo);
Tile t = m.GetTile(new Location(2, 2, 0)); //The problem line
Теперь, если я добавлю точку останова в свой код, я ясно вижу, что мой экземпляр (m) класса карты заполняется парами с помощью указанной выше функции, но когда я пытаюсь получить доступ к значению с помощью функции GetTile:
public Tile GetTile(Location location)
{
if(this.tiles.ContainsKey(location))
{
return this.tiles[location];
}
else
{
return null;
}
}
ВСЕГДА возвращает ноль. Опять же, если я просматриваю объект Map и нахожу ключ Location, где x=2,y=2,z=0, я ясно вижу значение Tile, сгенерированное FillTemp.
Почему он это делает? У меня не было проблем с таким словарём, как этот. Я понятия не имею, почему он возвращает ноль. и опять же, при отладке я Ясно вижу, что экземпляр Map содержит ключ Location, который, как он говорит, не... очень расстраивает.
Есть какие-нибудь подсказки? Нужна дополнительная информация?
Помощь будет принята с благодарностью:)
3 ответа
Вы не показываете, что такое "Location", но это нормальное поведение, если это класс: объекты проверяются на равенство путем сравнения ссылок. Таким образом, разные экземпляры Location всегда будут неравными, даже если их содержание одинаково.
Самое быстрое решение - переопределить Equals() и GetHashCode() для класса Location. И тогда будет хорошей идеей (пере) разработать его как неизменяемый класс (или, может быть, неизменную структуру).
Хенк прав; когда вы проверяете, равны ли два объекта в.Net, вы фактически спрашиваете, указывает ли "ссылка x на тот же объект, что и ссылка y".
Итак, по умолчанию:
Location a = new Location(2, 2, 0);
Location b = new Location(2, 2, 0);
Location c = a;
bool notEqual = ( a == b ); // false
bool equal = ( a == c ); // true
Чтобы обойти это, вам нужно переопределить методы равенства для вашего объекта Location, чтобы сравнить значения для равенства - тело вашего Equals
метод, например, может закончить нас как что-то вроде:
return (this.x == that.x && this.y == that.y && this.z == that.z);
Всем спасибо! Я очень ценю это!
Я превратил Location в тип значения, и теперь он работает просто отлично.
Я извиняюсь за то, что не опубликовал весь код, но я не чувствовал в этом необходимости и предположил, что читатель может предположить, что location - это простой класс со значениями x,y,z int.
Из-за всех вас я узнал много нового, и мое понимание этого (вообще) замечательного языка стало лучше из-за этого: o)
Береги себя,