Каковы способы различения объектов одного типа для поиска, сравнения и т. д. в С#

Прошу прощения за странный заголовок, я не знал, как задать вопрос, поэтому, если у вас есть какие-либо предложения относительно того, что было бы более подходящим, дайте мне знать, и я обновлю его.

Часто при программировании я использовал перечисления в качестве ключей к словарям, значения которых являются данными, относящимися к перечислению. Обычно я делаю это до того, как понимаю, что с этим перечислением связано много данных, что затем приводит меня к созданию типа данных.

Например, у меня может быть перечисление:

public enum AreaKey
{
    Home,
    Hospital,
    Park,
    TrainStation
}

а затем словарь (Vector2 - это класс с двумя целыми числами):

Dictionary<AreaKey, Vector2> areaCoordinatesByAreaKey;

Позже я решаю, что мне нужна куча других данных, связанных с этой областью, поэтому вместо этого я создаю новый класс с именем:

    public class Area
    {
        Vector2 coordinates;
        string name;
        // more data
    }

Теперь, чтобы сослаться на эти данные, я знаю, что могу просто создать словарь, используя то же перечисление, что и ключ, для извлечения указанной области, но это всегда кажется мне громоздким и почти как неправильный ООП.

У меня есть объекты области. У них есть определенные данные, которые должны отличать их друг от друга. Почему я должен использовать перечисление? Также мне не нравится ломать OCP каждый раз, когда я понимаю, что мне нужна новая область. Было бы здорово иметь возможность просто создать объект и не беспокоиться о внешнем управлении. Однако поиск порядка 1 хорош.

Конечно, я мог бы использовать строковый ключ для его извлечения, но это означает, что люди должны знать строки, и это не очень безопасно для типов... перечисления легко читать. Помогите мне переполнить стек!


person Sebastian King    schedule 21.11.2018    source источник
comment
Во многом это зависит от того, как вы хотите их использовать. Наличие словаря из Area объектов с ключом AreaKey кажется немного странным, потому что у вас всегда будет только одна область каждого типа.   -  person Evan Trimboli    schedule 22.11.2018
comment
Это ненужное запутывание. Что не так с обычным классом/экземпляром со свойствами? Они читаются как заклинание. Почему я должен использовать перечисление?... для этого вы этого не сделаете. Я не понимаю, почему ты это сделал.   -  person spender    schedule 22.11.2018
comment
Я предполагаю, что использование enum связано с тем, что люди должны знать строки. В этой проблеме есть целая часть, о которой вы на самом деле не написали, и именно поэтому вы сюда попали в первую очередь (я полагаю, что это некоторая часть пользовательского интерфейса, из которого пользователи отправляют данные).   -  person spender    schedule 22.11.2018
comment
Использование словаря, который может хранить только 4 объекта, — это тяжелый запах кода. Трудно предположить, как это произошло, мозговые ошибки, как правило, трудно идентифицировать по фрагменту кода. Вы только наполовину обнаружили, что что-то пошло не так, подумайте еще немного об идентичности объекта.   -  person Hans Passant    schedule 22.11.2018
comment
Я думаю, это может быть связано с тем, что мы часто используем синглтоны в нашем коде (не я лично, а наша команда). Синглтон будет содержать кучу данных (например, области), и нам нужно будет получить области, поэтому мы будем использовать словари с ключом enum... Может ли это быть связано?   -  person Sebastian King    schedule 22.11.2018
comment
@spender может быть 100 областей, было бы громоздко писать 100 экземпляров класса. Вместо этого мы группируем их в контейнер. Словарь, а не массив, поэтому мы можем использовать перечисление, чтобы легко определить, какой из них мы пытаемся получить. Возможно, я должен упомянуть, что мы используем игровой движок (Unity), где мы можем перетаскивать ссылки на наши объекты. Мы перетаскиваем их в словарь через интерфейс (поэтому нам не нужно реализовывать каждый в коде).   -  person Sebastian King    schedule 22.11.2018
comment
Почему наличие 100 из них делает его еще более громоздким? Вам все еще нужно создать экземпляры и добавить их в словарь: /а>   -  person Evan Trimboli    schedule 22.11.2018
comment
Хорошо, теперь я вижу. Это должно быть чисто конкретной проблемой среды программирования. Я программирую в игровом движке Unity3D. Мы можем применять сценарии к объектам (например, сценарий области). Посмотрите сами: imgur.com/bOYE4ik Слева у вас есть перечисление, а справа у вас есть ссылка на объект... извините, если честно, иногда я так запутался, с чем, черт возьми, я борюсь   -  person Sebastian King    schedule 22.11.2018
comment
Может случиться так, что накладные расходы на использование этого метода - все проблемы, которые я описал... Может быть, нет никакого способа обойти это.   -  person Sebastian King    schedule 22.11.2018
comment
Не уверен насчет части Unity, поэтому на этом этапе мне придется откланяться.   -  person Evan Trimboli    schedule 22.11.2018
comment
@EvanTrimboli Спасибо за попытку помочь, теперь я лучше понимаю свою проблему.   -  person Sebastian King    schedule 22.11.2018


Ответы (1)


Это полностью зависит от того, как вы собираетесь получить объект. Например, как правило, при создании приложений WinForms (до того, как я узнал о волшебстве привязки данных) и я добавлял элементы, чтобы сказать ListBox, я мог бы захотеть запомнить положение каждого объекта в списке, чтобы я мог легко получить его позже. Я бы создал Dictionary<Foo, int>. Точно так же я могу захотеть разрешить быстрый поиск на основе позиции в списке, чтобы у меня был Dictionary<int, Foo>. Другими словами, не пытайтесь хранить все в одном Dictionary<>. Определите их по вариантам использования.

Вы уже определили один с помощью AreaKey, и это предполагает, что нет двух объектов с одинаковым перечислением, поэтому использование словаря в этом случае имеет смысл. Однако я думаю, что вы идете по ложному пути, пытаясь свести все к одному ключу. Вместо этого вы можете захотеть иметь еще один Dictionary<string, Area>, где он ссылается на Area.name, чтобы вы могли искать не только по перечислению, но и по имени.

Позже вы, возможно, захотите добавить PostCode, так что еще один Dictionary<int, Area> имеет смысл.

Подводя итог, определите:

Dictionary<string, Area> mapAreasByName;
Dictionary<int, Area> mapAreasByPostCode;

var area = mapAreasByName["New York"];
area = mapAreasByPostCode[2000];
person MickyD    schedule 21.11.2018