#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
Комментариев нет:
Отправить комментарий