Ist es möglich, eine allgemeine bitweise Aufzählung ‚IsOptionSet ()‘ Methode zu schaffen?

StackOverflow https://stackoverflow.com/questions/1614412

Frage

Der Code unten macht es einfach, in einem Satz HtmlParserOptions passiert und dann zu prüfen, gegen eine einzige Option, um zu sehen, ob es ausgewählt worden ist.

[Flags]
public enum HtmlParserOptions
{
    NotifyOpeningTags = 1,
    NotifyClosingTags = 2,
    NotifyText = 4,
    NotifyEmptyText = 8
}

private bool IsOptionSet(HtmlParserOptions options, HtmlParserOptions singleOption)
{
    return (options & singleOption) == singleOption;
}

Meine Frage ist, ist es möglich, eine generische Ausführung dieses zu erstellen (Ich vermute, durch eine Schnittstelle auf der Methode Eigenschaften Implementierung), die mit arbeiten jedem Aufzählung mit der Flags-Attribute

War es hilfreich?

Lösung

Edit:

Die einfachste, schönste Möglichkeit ist, VS2010 Beta2 zu aktualisieren und .NET 4 der Enum.HasFlag Methode. Das Framework-Team hat viele nette Ergänzungen Enum hinzugefügt, um sie schöner zu verwenden, um zu machen.


Original (für aktuelle .NET):

Sie können dies tun, indem Enum vorbei, statt Generika:

static class EnumExtensions
{
    private static bool IsSignedTypeCode(TypeCode code)
    {
        switch (code)
        {
            case TypeCode.Byte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
                return false;
            default:
                return true;
        }
    }

    public static bool IsOptionSet(this Enum value, Enum option)
    {
        if (IsSignedTypeCode(value.GetTypeCode()))
        {
            long longVal = Convert.ToInt64(value);
            long longOpt = Convert.ToInt64(option);
            return (longVal & longOpt) == longOpt;
        }
        else
        {
            ulong longVal = Convert.ToUInt64(value);
            ulong longOpt = Convert.ToUInt64(option);
            return (longVal & longOpt) == longOpt;
        }
    }
}

Das funktioniert perfekt, etwa so:

class Program
{
    static void Main(string[] args)
    {
        HtmlParserOptions opt1 = HtmlParserOptions.NotifyText | HtmlParserOptions.NotifyEmptyText;
        Console.WriteLine("Text: {0}", opt1.IsOptionSet(HtmlParserOptions.NotifyText));
        Console.WriteLine("OpeningTags: {0}", opt1.IsOptionSet(HtmlParserOptions.NotifyOpeningTags));

        Console.ReadKey();
    } 
}

Der oben gezeigten Druck:

Text: True
OpeningTags: False

Der Nachteil dieses aber ist es nicht, dass Sie von vorbeifahrenden zwei verschiedene Arten von Enum-Typen in die Routine schützt. Sie haben es zu benutzen, vernünftig.

Andere Tipps

Nun, irgendwie.

Sie können keinen Zwang, um sicherzustellen, hinzufügen, dass das Typargument ein „flags“ Enum ist und einfach in C # können Sie nicht eine Einschränkung hinzufügen, um sicherzustellen, dass es eine Enum in erster Linie ... aber mit ein bisschen Schmu können Sie diese an die Arbeit. Es ist eine gültige Beschränkung in IL, aber nicht in C #. Sie würden dann ein bisschen Arbeit tun müssen, um zu bekommen, das „und“ Teil arbeitet allgemein.

Ich habe ein Projekt namens Unconstrained Melody , die einige nützliche Erweiterungsmethoden auf Aufzählungen hat über eine gewissen IL-neu zu schreiben. In diesem Fall würden Sie verwenden:

if (options.HasAny(optionToTest))

oder

if (options.HasAll(optionToTest))

Je nachdem, wie Sie wollten den Fall behandeln, wo optionToTest tatsächlich mehrere kombinierte Flaggen sind.

Alternativ warten .NET 4.0 - die Änderungen der BCL Enum.HasFlag , was ich denke, das tun, was Sie wollen.

public static bool IsOptionSet<T>(this T flags, T option) where T : struct
{
    if(! flags is int) throw new ArgumentException("Flags must be int");

    int opt = (int)(object)option;
    int fl = (int)(object)flags;
    return (fl & opt) == opt;
}

EDIT: Wie bereits in den Kommentaren darauf hingewiesen, das wird nicht funktionieren, wenn die ENUM etwas anderes als ein int ist (die Standardeinstellung für Aufzählungen ist). Es soll wohl etwas anderes zu zeigen, diese benannt werden, aber es ist wahrscheinlich ‚gut genug‘ für die Mehrheit der Fälle, wenn Sie eine Reihe von Flaggen mit mehr als 31 Werten müssen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top