2012-11-19 11 views
5

ich eine Erweiterungsmethode als solche erstellt haben ..Überprüfen Sie, ob ausschließlich nur diese in Aufzählung gesetzt Flags

public static bool AllFlagsSet<T>(this T input, params T[] values) where T : struct, IConvertible 
{ 
    bool allSet = true; 
    int enumVal = input.ToInt32(null); 

    foreach (T itm in values) 
    { 
     int val = itm.ToInt32(null); 
     if (!((enumVal & val) == val)) 
     { 
      allSet = false; 
      break; 
     } 
    } 

    return allSet; 
} 

die für die Zwecke funktioniert gut ich brauchte, aber ich habe jetzt eine Anforderung, ein Verfahren zu schaffen, mit der gleiche Signatur, die prüft, ob nur diese Werte gesetzt wurden.

Grundsätzlich so etwas.

public static bool OnlyTheseFlagsSet<T>(this T input, params T[] values) where T : struct, IConvertible 
{ 
} 

Die einzige Möglichkeit, die ich denken kann, dies zu tun ist, indem sie alle verfügbaren Enumerationswerten Prüfung erhalten die eingestellt werden, und bestätigt, dass nur die beiden zur Verfügung gestellt wurden.

Gibt es eine andere Möglichkeit, dieses Problem mit einer bitweisen Operation zu lösen?

+0

Ist das eine Hausaufgaben ?? Und warum ist T Constraint zu einer Struktur und nicht zu einer Enum ?? – LightStriker

+0

lol, nun, das ist peinlich. Nein, ich habe noch kein festes Verständnis für bitweise Operationen ... Das ist eine echte Anforderung –

+0

Versuchen Sie, es auf Enum zu beschränken und sehen Sie, was passiert. ;-p –

Antwort

5

Do "oder" auf allen erforderlichen Flags und vergleichen mit Eingabe - sollte gleich sein. Ähnlich wie folgt, mit der richtigen Schleifenwert auf der linken Seite zu berechnen:

var onlyTheseFlagsSet = (value[0] | value[1]) == input; 
0

bin ich etwas fehlt oder konnte man nicht einfach Summe params T [] Werte und prüfen, ob Eingabe das Ergebnis ist gleich?
Wenn Sie nur diese Flags und keine anderen möchten, sollte die Eingabe der Summe dieser Flags entsprechen.

+1

Sum als '+' kann gefährlich sein, da Enum-Werte selbst für Flag-Typen sich nicht gegenseitig ausschließen müssen - man muss '| 'verwenden, um Flags richtig zu kombinieren. –

1

Damit wird das Bit jedes Eingabewerts umgedreht. Wenn nur diese gesetzt sind, ist der resultierende Wert Null. Andernfalls werden die Bits auf 1 zurückgesetzt, wenn der Wert nicht in input gesetzt ist, wodurch der Wert ungleich Null bleibt.

public static bool OnlyTheseFlagsSet<T>(this T input, params T[] values) where T : struct, IConvertible 
{ 
    int enumVal = input.ToInt32(null); 

    foreach (T itm in values) 
    { 
     int val = itm.ToInt32(null); 
     enumVal = enumVal^val;     
    } 

    return (enumVal == 0); 
} 
+1

+1. Ich mag '' 'Ansatz, aber dieser ist auch interessant. Randnotiz - bitte vermeiden Sie snrng nms f vrbls wie 'itm' anstelle von' item'. –

+0

Ich mag den '|' Ansatz auch mehr. Vereinbart mit Variablennamen, behielt ich nur den Stil des ursprünglichen Autors bei. –

+0

Randnotiz: gerade bemerkt - Ihr Code beruht auf gegenseitig ausschließenden Werten ... nicht unbedingt auch für Werte von Enum, die als Flags markiert sind. –

0

Vorausgesetzt, dass Sie Ihre Eingabe in einen Enum umwandeln kann:

foreach(MyFlags flag in values) 
    if (!input.HasFlag(flag)) 
     return false; 

return true; 

Ja, ich bin faul so.

+0

Ich denke OP möchte auch sicherstellen, dass andere Flags nicht gesetzt sind ... warten auf OPs Kommentare ... –

2

Exclusivity Anforderung bedeutet, dass

input = values[0] | values[1] | ... | values[values.Length - 1]

So, hier Ihre Implementierung ist:

return input.ToInt32(null) == values.Aggregate(0, 
     (total, next) => total | next.ToInt32(null)); 
+0

+1. Das '.ToInt32 (null)' sieht komisch aus, funktioniert aber trotzdem! –

Verwandte Themen