Использование структуры в качестве ключа для словаря и странные вещи происходят
Вот моя структура...
internal struct Coord : IEquatable<Coord>
{
public int X { get; private set; }
public int Y { get; private set; }
public Coord(int x,int y) : this(){ X = x;
Y = y;}
//Overloaded operator functuions below
//So I can easily multiply Coords by other Coords and ints and also add Coords together
public static Coord operator *(Coord left, int right)
{
return new Coord(left.X * right, left.Y * right);
}
public static Coord operator *(Coord left, Coord right)
{
return new Coord(left.X * right.X, left.Y * right.Y);
}
public static Coord operator +(Coord left, Coord right)
{
return new Coord(left.X + right.X, left.Y + right.Y);
}
public static Coord operator -(Coord left, Coord right)
{
return new Coord(left.X - right.X, left.Y - right.Y);
}
public override int GetHashCode()
{
int hash = 17;
hash = hash * 31 + X;
hash = hash * 31 + Y;
return hash;
}
public override bool Equals(object other)
{
return other is Coord ? Equals((Coord)other) : false;
}
public bool Equals(Coord other)
{
return X == other.X &&
Y == other.Y;
}
}
Я использую их как ключи для словаря, но я не думаю, что они приравниваются друг к другу должным образом. Значения в словаре являются объектами с полем bool. У меня есть цикл while, который делает с ними что-то и меняет bool на true, пока все они не становятся true. Он застревает в бесконечном цикле, так как они никогда не меняются на true. Что странно в том, что я не получаю ничего вне диапазона ошибки или что-то в этом роде, и когда я отлаживаю бит, где изменяется bool, кажется, что он работает нормально, но когда я смотрю на словарь в отладке, все bool все еще ложны
(примечание: я использовал Tuple в качестве ключа, но я создал эту структуру, чтобы можно было легко умножать и добавлять их)
Я просто хочу уточнить, что с тобой...
_myDictionary = new Dictionary<Coord, RogueRoom>();
_myDictionary[new Coord(4,5)] = new RogueRoom();
_myDictionary[new Coord(4,5)].Connected = true
Те два раза, когда я получаю доступ к словарю, я получаю доступ к одному и тому же значению объекта?
РЕДАКТИРОВАТЬ: Вот структура значений в словаре (я заменил "вещь" выше)
internal struct RogueRoom
{
public Room RoomField;
public bool Connected;
public Rectangle Realpos;
public Color[] RogueRoomColors;
public Coord Gridpos;
}
2 ответа
Это зависит от того, что Thing
является. Если Thing
это struct
: нет; значение копируется при получении - хотя компилятор обычно останавливает назначение свойств для struct
это собирается быть выброшенным. Если это class
тогда это должен быть тот же экземпляр объекта; ваш равный / хэш-код выглядит разумно.
Ваше заявление _myDictionary[new Coord(4,5)].Connected = true;
не должен компилироваться, так как методы и свойства, чей тип возврата является структурой (например, _myDictionary[new Coord(4,5)]
) вернуть копии только для чтения этих типов структур, и вы пытаетесь записать в такую структуру только для чтения.
Для краткости, я собираюсь сделать вид, что ваш словарь был Dictionary<int, RogueRoom>
; дело в том, что Coordinate
является определяемой пользователем структурой, здесь не имеет значения.
Если вы говорите var temp = _myDictionary[5];
это утверждение будет генерировать доступную для записи копию RogueRoom
пример. Если вы говорите temp.Connected=true;
это изменит эту копию, но оставит копию в словаре без изменений. Если вы хотите обновить файл, хранящийся в словаре, вам придется написать его обратно самостоятельно: _myDictionary[5] = temp;
,
Если бы вы должны были изменить RogueRoom
в изменчивый класс, то вы могли бы сказать, _myDictionary[5].Connected = true;
изменить Connected
свойство объекта, связанного с 5. Однако, к лучшему или к худшему, оно также изменило бы Connected
свойство, связанное с любой другой ссылкой, которая существует на тот же объект. Например, если сказать _MyDictionary[2] = _MyDictionary[5];
тогда утверждение _myDictionary[5].Connected = true;
установит свойство connected объекта, связанного с 2 (поскольку объект, связанный с 2, является тем же объектом, что и связанный с 5).
Некоторым людям не нравятся изменчивые структуры, и они советуют вам разрабатывать свой тип так, чтобы код должен был что-то вроде:
var temp = _myDictionary[5];
_myDictionary[5] = new RogueRoom(temp.RoomField, true, temp.RealPos,
temp.RogueRoomColors, temp.GridPos);
вместо того, чтобы просто обновить Connected
собственностью temp
и писать это обратно. Я считаю, что последний стиль излишне уродлив и неясен, но некоторые люди предпочитают его.
Что касается вопроса о том, должна ли вещь быть классом, это зависит от того, хотите ли вы каждое место хранения типа RogueRoom
хранить пять независимых фрагментов информации, которые не зависят от тех, которые находятся в любом другом хранилище этого типа, или хотите ли вы разрешить нескольким хранилищам этого типа ссылаться на один и тот же экземпляр. Есть определенные варианты использования для обоих сценариев; вам нужно определить, что подходит именно вам.