Co to jest tylda ( ~ ) w definicji enum?

Jestem zawsze zaskoczony, że nawet po używaniu C# przez cały ten czas, wciąż udaje mi się znaleźć rzeczy, o których nie wiedziałem...

Próbowałem przeszukiwać internet w poszukiwaniu tego, ale użycie " ~ " w wyszukiwaniu nie działa dla mnie tak dobrze i nie znalazłem nic na MSDN albo (nie mówiąc, że nie ma)

Widziałem ostatnio ten fragment kodu, co oznacza tylda (~)?

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

Byłem trochę zaskoczony, widząc to, więc próbowałem go skompilować i zadziałało... ale ja nadal Nie wiem, co to znaczy/robi. Jakaś pomoc??

Author: chue x, 2008-12-23

10 answers

~ jest unarnym operatorem dopełniacza -- odwraca bity swojego operandu.

~0 = 0xFFFFFFFF = -1

W arytmetyce dopełniacza dwójki, ~x == -x-1

Operator ~ można znaleźć w prawie każdym języku, który zapożyczył składnię z C, w tym Objective-C / C++/C#/Java / Javascript.

 131
Author: Jimmy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-29 14:35:28

Myślę, że:

[Flags]
public enum PurchaseMethod
{
    None = 0,
    Cash = 1,
    Check = 2,
    CreditCard = 4,
    All = Cash | Check | CreditCard
 }
Byłoby bardziej jasne.
 55
Author: Sean Bright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-22 21:42:59
public enum PurchaseMethod
{   
    All = ~0, // all bits of All are 1. the ~ operator just inverts bits
    None =  0,
    Cash =  1,
    Check =  2,
    CreditCard =  4
}

Z powodu dwóch dopełnień w C#, ~0 == -1, liczba, w której wszystkie bity są 1 w reprezentacji binarnej.

 20
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-22 21:47:33

Its better than the

All = Cash | Check | CreditCard

Rozwiązanie, bo jeśli dodasz później inną metodę, powiedz:

PayPal = 8 ,

Będziesz już gotowy z tyldą-All, ale musisz zmienić wszystkie linie z innymi. Więc jest mniej podatny na błędy później.

Pozdrawiam

 15
Author: blabla999,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-22 22:38:03

Tylko na marginesie, gdy używasz

All = Cash | Check | CreditCard

Masz dodatkową korzyść, która Cash | Check | CreditCard oceniłaby na All, a nie na inną wartość (-1), która nie jest równa wszystkim, a zawiera wszystkie wartości. Na przykład, jeśli użyjesz trzech pól wyboru w interfejsie

[] Cash
[] Check
[] CreditCard

I zsumować ich wartości, a użytkownik wybierze je wszystkie, zobaczysz All w wynikowym enum.

 10
Author: configurator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-22 23:00:36

Dla innych, którzy uznali to pytanie za pouczające, mam szybki przykład do podzielenia się. Poniższy fragment z implementacji metody malowania, jak opisano w tej dokumentacji Mono , wykorzystuje ~ do wspaniałego efektu:

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

Bez operatora ~ kod prawdopodobnie wyglądałby mniej więcej tak:

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

... ponieważ wyliczenie wygląda tak:

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
}

Zauważyłeś podobieństwo enum do odpowiedzi Seana Brighta?

Myślę, że najważniejsze dla mnie jest to, że ~ jest tym samym operatorem w enum, co w normalnej linii kodu.

 9
Author: Mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-22 03:34:06

Jest operatorem dopełniacza, Oto artykuł, do którego często odwołuję się dla operatorów bitowych

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

Również msdn używa go w swoim artykule enums, który pokazuje, że używa go lepiej

Http://msdn.microsoft.com/en-us/library/cc138362.aspx

 5
Author: rizzle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-22 21:42:52

Alternatywa, której osobiście używam, która robi to samo, co odpowiedź @ Seana Brighta, ale wygląda dla mnie lepiej, to ta:

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

Zauważ, jak binarna natura tych liczb, które są potęgami dwóch, sprawia, że następujące twierdzenie jest prawdziwe: (a + b + c) == (a | b | c). I IMHO wygląda lepiej.

 1
Author: Camilo Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-21 03:05:03

Przeprowadziłem kilka eksperymentów z ~ i okazało się, że może mieć pułapki. Rozważ ten fragment dla Linqpada, który pokazuje, że wartość all enum nie zachowuje się tak, jak oczekiwano, gdy wszystkie wartości są orowane razem.

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
Author: Gavin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-15 13:55:37

Po prostu chcę dodać, jeśli używasz [Flags] enum, wtedy wygodniejsze może być użycie bitowego operatora przesunięcia w lewo, jak to:

[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
Author: sad_robot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-04 13:09:10