it-swarm.com.de

Was ist die Tilde (~) in der Enum-Definition?

Ich bin immer wieder überrascht, dass ich auch nach all der Zeit, in der ich C # verwendet habe, immer noch Dinge finde, von denen ich nichts wusste ...

Ich habe versucht, das Internet danach zu durchsuchen, aber die Verwendung des "~" bei einer Suche funktioniert bei mir nicht so gut und ich habe auch nichts auf MSDN gefunden (um nicht zu sagen, dass es nicht da ist)

Ich habe diesen Codeausschnitt kürzlich gesehen. Was bedeutet die Tilde (~)?

/// <summary>
/// Enumerates the ways a customer may purchase goods.
/// </summary>
[Flags]
public enum PurchaseMethod
{   
    All = ~0,
    None =  0,
    Cash =  1,
    Check =  2,
    CreditCard =  4
}

Ich war ein wenig überrascht, als ich es sah, also habe ich versucht, es zu kompilieren, und es hat funktioniert ... aber ich weiß immer noch nicht, was es bedeutet/tut. Irgendeine Hilfe??

143
Hugoware

~ ist der Komplementoperator des Unären - er kippt die Bits seines Operanden.

~0 = 0xFFFFFFFF = -1

in Zweierkomplementarithmetik, ~x == -x-1

der Operator ~ ist in nahezu jeder Sprache zu finden, die Syntax von C entlehnt hat, einschließlich Objective-C/C++/C #/Java/Javascript.

134
Jimmy

Ich würde das denken:

[Flags]
public enum PurchaseMethod
{
    None = 0,
    Cash = 1,
    Check = 2,
    CreditCard = 4,
    All = Cash | Check | CreditCard
 }

Wäre etwas klarer.

57
Sean Bright
public enum PurchaseMethod
{   
    All = ~0, // all bits of All are 1. the ~ operator just inverts bits
    None =  0,
    Cash =  1,
    Check =  2,
    CreditCard =  4
}

Wegen zweier Komplemente in C #, ~0 == -1, die Zahl, bei der alle Bits in der Binärdarstellung 1 sind.

Es ist besser als das

All = Cash | Check | CreditCard

lösung, denn wenn Sie später eine andere Methode hinzufügen, sagen Sie:

Paypal = 8 ,

sie werden bereits mit der Tilde-All fertig sein, müssen aber die All-Line mit der anderen ändern. Daher ist es später weniger fehleranfällig.

grüße

15
blabla999

Nur eine Randnotiz, wenn Sie verwenden

All = Cash | Check | CreditCard

sie haben den zusätzlichen Vorteil, dass Cash | Check | CreditCard würde zu All und nicht zu einem anderen Wert (-1) ausgewertet, der nicht gleich all ist, während alle Werte enthalten sind. Wenn Sie beispielsweise drei Kontrollkästchen in der Benutzeroberfläche verwenden

[] Cash
[] Check
[] CreditCard

wenn Sie die Werte summieren und der Benutzer sie alle auswählt, sehen Sie All in der resultierenden Aufzählung.

10
configurator

Für andere, die diese Frage aufschlussreich fanden, habe ich ein kurzes ~ Beispiel zum Teilen. Der folgende Ausschnitt aus der Implementierung einer Paint-Methode, wie in diese Mono-Dokumentation beschrieben, verwendet ~ mit großer Wirkung:

PaintCells (clipBounds, 
    DataGridViewPaintParts.All & ~DataGridViewPaintParts.SelectionBackground);

Ohne das ~ Operator, der Code würde wahrscheinlich ungefähr so ​​aussehen:

PaintCells (clipBounds, DataGridViewPaintParts.Background 
    | DataGridViewPaintParts.Border
    | DataGridViewPaintParts.ContentBackground
    | DataGridViewPaintParts.ContentForeground
    | DataGridViewPaintParts.ErrorIcon
    | DataGridViewPaintParts.Focus);

... weil die Aufzählung so aussieht:

public enum DataGridViewPaintParts
{
    None = 0,
    Background = 1,
    Border = 2,
    ContentBackground = 4,
    ContentForeground = 8,
    ErrorIcon = 16,
    Focus = 32,
    SelectionBackground = 64,
    All = 127 // which is equal to Background | Border | ... | Focus
}

Beachten Sie die Ähnlichkeit dieses Enums mit der Antwort von Sean Bright?

Ich denke, das wichtigste für mich ist, dass ~ ist derselbe Operator in einer Enumeration wie in einer normalen Codezeile.

9
Mike

Es ist ein Komplementoperator. Hier ist ein Artikel, auf den ich mich oft für bitweise Operatoren beziehe

http://www.blackwasp.co.uk/CSharpLogicalBitwiseOps.aspx

Auch Msdn verwendet es in ihren Aufzählungsartikeln, die demonstrieren, dass es besser verwendet wird

http://msdn.Microsoft.com/en-us/library/cc138362.aspx

5
missaghi

Ich habe einige Experimente mit dem ~ gemacht und finde, dass es Fallstricke haben könnte. Betrachten Sie dieses Snippet für LINQPad, das zeigt, dass sich der All enum-Wert nicht wie erwartet verhält, wenn alle Werte zusammen geordnet sind.

void Main()
{
    StatusFilterEnum x = StatusFilterEnum.Standard | StatusFilterEnum.Saved;
    bool isAll = (x & StatusFilterEnum.All) == StatusFilterEnum.All;
    //isAll is false but the naive user would expect true
    isAll.Dump();
}
[Flags]
public enum StatusFilterEnum {
      Standard =0,
      Saved =1,   
      All = ~0 
}
1
Gavin

Die Alternative, die ich persönlich benutze und die das Gleiche tut wie die Antwort von @Sean Bright, aber für mich besser aussieht, ist die folgende:

[Flags]
public enum PurchaseMethod
{
    None = 0,
    Cash = 1,
    Check = 2,
    CreditCard = 4,
    Paypal = 8,
    BitCoin = 16,
    All = Cash + Check + CreditCard + Paypal + BitCoin
}

Beachten Sie, wie die binäre Natur dieser Zahlen, die alle Zweierpotenzen sind, die folgende Behauptung wahr macht: (a + b + c) == (a | b | c). Und meiner Meinung nach + sieht besser aus.

1
Camilo Martin

Wollen Sie nur hinzufügen, wenn Sie [Flags] enum verwenden, ist es möglicherweise praktischer, den bitweisen Links-Shift-Operator wie folgt zu verwenden:

[Flags]
enum SampleEnum
{
    None   = 0,      // 0
    First  = 1 << 0, // 1b    = 1d
    Second = 1 << 1, // 10b   = 2d
    Third  = 1 << 2, // 100b  = 4d
    Fourth = 1 << 3, // 1000b = 8d
    All    = ~0      // 11111111b
}
0
sad_robot