Building a summary string from a flags enum I'm trying to replicate the attributes text that appears in File Explorer, for files and directories.

I can't just use the enum names, as the summary text uses a single character for each set flag, and that character isn't always the first character of the enum member. I'm also not using the reserved FileAttribute.Device attribute. So, I'm using a string.join operation to concatenate the flag characters.

    public string AttributeSummary
    {
        get
        {
            FileAttributes fatt = (FileAttributes)_attribs;

            return string.Join(string.Empty,
                (fatt.HasFlag(FileAttributes.ReadOnly) ?          "R" : string.Empty),
                (fatt.HasFlag(FileAttributes.Hidden) ?            "H" : string.Empty),
                (fatt.HasFlag(FileAttributes.System) ?            "S" : string.Empty),
                (fatt.HasFlag(FileAttributes.Directory) ?         "D" : string.Empty),
                (fatt.HasFlag(FileAttributes.Archive) ?           "A" : string.Empty),
                (fatt.HasFlag(FileAttributes.Normal) ?            "N" : string.Empty),
                (fatt.HasFlag(FileAttributes.Temporary) ?         "T" : string.Empty),
                (fatt.HasFlag(FileAttributes.SparseFile) ?        "P" : string.Empty),
                (fatt.HasFlag(FileAttributes.ReparsePoint) ?      "L" : string.Empty),
                (fatt.HasFlag(FileAttributes.Compressed) ?        "C" : string.Empty),
                (fatt.HasFlag(FileAttributes.Offline) ?           "O" : string.Empty),
                (fatt.HasFlag(FileAttributes.NotContentIndexed) ? "I" : string.Empty),
                (fatt.HasFlag(FileAttributes.Encrypted) ?         "E" : string.Empty),
                (fatt.HasFlag(FileAttributes.IntegrityStream) ?   "V" : string.Empty),
                (fatt.HasFlag(FileAttributes.NoScrubData) ?       "X" : string.Empty));
        }
    }


Am I going about this in the most efficient way?
Am I going about this in the most efficient way?


If you're worried about efficiency, then Enum.HasFlag is known to be fairly slow.

Instead, I would use a very simple helper method:

private static bool HasFlag(FileAttributes value, FileAttributes flag)
    =&gt; value &amp; flag != 0;


Though if you're doing that, you might as well expand the helper function to give you the flag character:

private static string GetAttributeCharacter(
    FileAttributes value, FileAttributes flag, string character)
    =&gt; (value &amp; flag != 0) ? character : string.Empty;




I'm on the fence whether the helper method should access _attribs directly or whether it should get its value in a parameter. On one hand, reading the field over and over is likely going to be slower. On the other hand, that's the kind of microoptimization that does not matter in the vast majority of cases and accessing it directly would remove quite a lot of duplicated code.



Using string.Concat(…) instead of string.Join(string.Empty, …) is simpler and should be faster.



If you're on C# 6.0, you can avoid some code repetition by using using static System.IO.FileAttributes;.



If it's clear what type a variable is, like your fatt, most code styles accept using var for its type. Also, I think that abbreviations like fatt are generally not worth it: they save you some type, but make understanding the code later harder.

Also, I don't understand why is the cast to FileAttributes necessary, but I'm going to assume there is a good reason for it.



Put together:

private string GetAttributeCharacter(FileAttributes flag, string character)
    =&gt; ((FileAttributes)_attribs &amp; flag != 0) ? character : string.Empty;

public string AttributeSummary
{
    get
    {
        return string.Concat(
            GetAttributeCharacter(ReadOnly,          "R"),
            GetAttributeCharacter(Hidden,            "H"),
            GetAttributeCharacter(System,            "S"),
            GetAttributeCharacter(Directory,         "D"),
            GetAttributeCharacter(Archive,           "A"),
            GetAttributeCharacter(Normal,            "N"),
            GetAttributeCharacter(Temporary,         "T"),
            GetAttributeCharacter(SparseFile,        "P"),
            GetAttributeCharacter(ReparsePoint,      "L"),
            GetAttributeCharacter(Compressed,        "C"),
            GetAttributeCharacter(Offline,           "O"),
            GetAttributeCharacter(NotContentIndexed, "I"),
            GetAttributeCharacter(Encrypted,         "E"),
            GetAttributeCharacter(IntegrityStream,   "V"),
            GetAttributeCharacter(NoScrubData,       "X"));
    }
}