#c_sharp #множества
Есть некий метод, пусть public static bool IsNewFileActual(sting oldFile, string newFile, ComparsionFlags flags) сравнивающий 2 файла по набору критериев. Сами критерии, для наглядности, например, такие: сравнение по дате последней записи в файл, версия файла, MD5-хэш, размер файла. В зависимости от некоторых условий, должна формироваться переменная flags, которая будет задавать флаги для критериев проверки (например, флаг проверки по номеру версии будет справедлив для *.EXE и *.DLL, а вот для *.PNG или *.HTML он не нужен). В паскале (Delphi), я бы работал примерно так: type TComparsionFlags = set of (cfDate, cfVersion, cfHash, cfSize); var CF : TComparsionFlags; ... CF := []; CF := CF + [cfVersion]; ... СF := CF + [cfHash, cfSize]; ... CF := CF - [cfDate]; ... if (cfDate in CF) then begin ... end; Иными словами, описал бы множество с возможными флагами, и использовал бы средства языка для достижения своих целей. Насколько я знаю, аналога паскалевских множеств в C# в чистом виде нет, и в качестве замены можно использовать enum, что я и делаю: [Flags] public enum ComparsionFlags : byte { cfVersion = 1, cfSize = 2, cfDate = 4, cfHash = 8, } После чего перед вызовом метода IsNewFileActual объявляю переменную ComparsionFlags flags и далее задаю флаги так: flags = ComparsionFlags.cfSize | ComparsionFlags.cfDate | ComparsionFlags.cfHash; Как по мне, так это не очень удобно (по меньшей мере, как минимум, не лаконично), как для задания самой переменной flags, так и для проверок значений, которые переданы в этой переменной внутрь метода. Собственно, вопрос и в заголовке, и вот, более детально: Как наилучшим образом реализовать тип ComparsionFlags для использования переменных данного типа в качестве набора флагов? Может быть есть альтернативные, более удобные способы выполнить описанную задачу? Буду признателен за внимание и дельные советы/ответы. Спасибо. P.S. Думал про Listи HashTable, но есть ощущение, что это несколько не то... Например, ничто не мешает добавить в List какой-то флаг n раз, и при удалении этого флага из списка придется просматривать его весь, и удалять все вхождения этого флага (или флагов), т.е. получаем, что нужно довольно много обвязки вокруг списка делать.
Ответы
Ответ 1
Использование флагов выглядит достаточно лаконично. Если переписать код с Delphi, получится примерно так: ComparsionFlags CF = default(ComparsionFlags); CF = CF | ComparsionFlags.cfVersion; ... СF = CF | ComparsionFlags.cfHash | ComparsionFlags.cfSize; ... CF = CF & ~ComparsionFlags.cfDate; ... if (CF.HasFlag(ComparsionFlags.cfDate)) { ... } Если использовать using static, то имя enum можно опускать: using static ComparsionFlags; ... ComparsionFlags CF = default(ComparsionFlags); CF |= cfVersion; ... СF |= cfHash | cfSize; ... CF &= ~cfDate; ... if (CF.HasFlag(cfDate)) { ... } В противовес, можно использовать класс HashSet, как указано в соседнем ответе: HashSetflags = new HashSet (); CF.Add(ComparsionFlags.cfVersion); ... СF.UnionWith(new[]{ComparsionFlags.cfHash,ComparsionFlags.cfSize}); ... CF.Remove(ComparsionFlags.cfDate); ... if (CF.Contains(ComparsionFlags.cfDate)) { ... } Как можно заметить, в этом случае не обязательно делать значения enum флагами, то есть значения могут идти и подряд: 1,2,3..., а не 1,2,4... Ответ 2
Я бы написал HashSet
Комментариев нет:
Отправить комментарий