There is a certain method, let the public static bool IsNewFileActual(sting oldFile, string newFile, ComparsionFlags flags) compare 2 files by a set of criteria. The criteria themselves, for clarity, for example, are: comparison by the date of the last entry in the file, file version, MD5-hash, file size.

Depending on some conditions, the flags variable should be formed, which will set flags for verification criteria (for example, the verification flag by version number will be valid for * .EXE and * .DLL, but for * .PNG or * .HTML it is not needed ).

In Pascal (Delphi), I would work something like this:

 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; 

In other words, I would describe the set with possible flags, and use the means of the language to achieve its goals.

As far as I know, there is no analogue of Pascal sets in C # in its pure form, and you can use enum as a replacement, which I do:

 [Flags] public enum ComparsionFlags : byte { cfVersion = 1, cfSize = 2, cfDate = 4, cfHash = 8, } 

After that, before calling the IsNewFileActual method, IsNewFileActual declare the variable ComparsionFlags flags and then set the flags like this:

 flags = ComparsionFlags.cfSize | ComparsionFlags.cfDate | ComparsionFlags.cfHash; 

As for me, this is not very convenient (at least, at least, not concisely), both for setting the flags variable itself, and for checking the values ​​that are passed into this variable inside the method.

Actually, the question is in the title, and here, in more detail:

What is the best way to implement the ComparsionFlags type to use variables of this type as a set of flags?

Maybe there are alternative, more convenient ways to perform the described task?

I would appreciate the attention and good advice / answers. Thank.

PS I thought about List<T> and HashTable , but there is a feeling that this is somewhat wrong ... For example, nothing prevents you from adding a flag to the List n times, and when you remove this flag from the list, you will have to view it all, and delete all occurrences of this flag (or flags), i.e. We get what we need quite a lot of strapping around the list.

  • four
    The way in which you perform the described task is optimal. About conciseness: The code for declaring and using bit flags on Delphi is not particularly compact. If you shorten the name of your enumeration to CompFl, remove the explicit indication of the enumeration values ​​(as I recall, the compiler can do this for you) and write everything down in a string that is more compact than on delphi - Alexey
  • 2
    This beautiful or ugly way is the best. More concisely - use constants 1 2 4 8 directly, perhaps even so 1/*version*/ | 2/*size*/ 1/*version*/ | 2/*size*/ - nick_n_a
  • one
    There is such a thing as HashSet , look also in her direction. - Mirdin
  • one
    Thought about List <T> and HashTable - HashSet stores only unique values - Grundy
  • one
    Well, the answers and comments are quite comprehensive, thank you so much! For myself, among other things, I opened another article in which I reviewed and provided references to some of the implementations in C # of the sets (set of ...) and operations with them. I hope this information will be useful if someone else has a similar question. For my own task, I did not reinvent the wheel with triangular wheels and multiply entities, leaving its implementation through enum and taking into account some of the utility given in [this answer] (ht - BlackWitcher

2 answers 2

Using flags looks quite concise. If you rewrite the code with Delphi, you get something like this:

 ComparsionFlags CF = default(ComparsionFlags); CF = CF | ComparsionFlags.cfVersion; ... СF = CF | ComparsionFlags.cfHash | ComparsionFlags.cfSize; ... CF = CF & ~ComparsionFlags.cfDate; ... if (CF.HasFlag(ComparsionFlags.cfDate)) { ... } 

If using using static , then the name enum can be omitted:

 using static ComparsionFlags; ... ComparsionFlags CF = default(ComparsionFlags); CF |= cfVersion; ... СF |= cfHash | cfSize; ... CF &= ~cfDate; ... if (CF.HasFlag(cfDate)) { ... } 

In contrast, you can use the HashSet class, as indicated in the adjacent answer:

 HashSet<ComparsionFlags> flags = new HashSet<ComparsionFlags>(); CF.Add(ComparsionFlags.cfVersion); ... СF.UnionWith(new[]{ComparsionFlags.cfHash,ComparsionFlags.cfSize}); ... CF.Remove(ComparsionFlags.cfDate); ... if (CF.Contains(ComparsionFlags.cfDate)) { ... } 

As you can see, in this case it is not necessary to make the enum values ​​flags, that is, the values ​​can go in a row: 1,2,3 ... and not 1,2,4 ...

    I would write HashSet<ComparsionFlags>

    • @Ksenia, why? quite a solution: use a specific class - Grundy