Я заметил одну ошибку в кодировании (при использовании .Net). Вы объявляете класс данных, который должен иметь поле словаря (или get/set Property), назовем его для примера 'Properties'. У него есть строковый тип ключа.
public System.Collections.Generic.Dictionary<string, object> Properties { get; set; }
Возможно, мы захотим использовать его как обычный класс данных. Таким образом, мы можем десериализовать JSON или строки SQL или что-то еще, чтобы заполнить словарь свойств. По счастливой случайности, наш сериализатор JSON понимает тип словаря и может сделать это довольно хорошо. НО (и тут возникает проблема...) в нашей бизнес-логике мы хотим, чтобы этот словарь не учитывал регистр при обработке ключей.
"Хорошо, нет проблем", - скажете вы. "Словари могут это делать. Каждый раз, когда мы пишем код, инициализирующий словарь класса, мы будем делать вот так:
Properties = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase)
Видите ли вы проблему в этом? Потому что мы поместили туда публичный сеттер. Любой может вызвать этот сеттер словаря и поместить в наш объект словарь с учетом регистра. И Мерфи уверяет нас, что так оно и будет; не из дурных побуждений, конечно, но потому что слишком легко забыть необязательный параметр StringComparer в Dictionary.
И что еще хуже, у нас есть код, который нам не принадлежит, в нашем десериализаторе JSON или фреймворке отображения объектов, который не удосуживается использовать StringComparer. Или, возможно, он просто выбирает неправильный, например, StringComparer.CurrentCultureIgnoreCase или OrdinalIgnoreCase. Это явно катастрофа, которая только и ждет, чтобы произойти. Что же нам делать?
Видите ли вы проблему в этом? Потому что мы поместили туда публичный сеттер.
Так что не надо публичного сеттера.
Создайте новый класс CaseInsensitiveDictionary
, который содержит приватный Dictionary
, инициализированный с нечувствительностью к регистру. Выставляйте этот приватный Dictionary
только через методы для взаимодействия с ним (например, add, remove и т.д.) - или предоставляйте только get
доступ к нему. Вы, вероятно, захотите реализовать IEnumerable
, IDictionary
и другие интерфейсы.
public sealed class CaseInsensitiveDictionary<string,TValue>
{
private Dictionary<string, TValue> _dictionary = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
// ... constructors, add, remove, etc methods
}
Везде, где вы используете Dictionary
сейчас, замените его на этот новый класс. Если вам нужно обрабатывать десериализацию JSON и т.д., вы можете предоставить методы для этого в новом классе.
Это похоже на то, что делается в .NET framework - например, Dictionary
vs SortedList
- новый класс создается, когда необходимо ограничение (упорядочивание).