development

열거 형 정의에서 물결표 (~)는 무엇입니까?

big-blog 2020. 6. 16. 07:53
반응형

열거 형 정의에서 물결표 (~)는 무엇입니까?


지금까지 C #을 사용한 후에도 여전히 알지 못하는 것을 찾을 수 있다는 사실에 항상 놀랐습니다 ...

인터넷에서 검색을 시도했지만 검색에서 "~"를 사용하면 제대로 작동하지 않으며 MSDN에서 아무것도 찾지 못했습니다 (존재하지 않음)

최근 에이 코드 스 니펫을 보았는데 물결표 (~)는 무엇을 의미합니까?

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

나는 그것을 보려고 조금 놀랐다. 그래서 그것을 컴파일하려고 시도했지만 효과가 있었다. 그러나 나는 그것이 무엇을 의미하는지 / 정확히 모른다. 어떤 도움?


~는 단항 보수 연산자입니다-피연산자의 비트를 뒤집습니다.

~0 = 0xFFFFFFFF = -1

2의 보수 산술에서 ~x == -x-1

~ 연산자는 Objective-C / C ++ / C # / Java / Javascript를 포함하여 C에서 구문을 빌린 거의 모든 언어에서 찾을 수 있습니다.


나는 그렇게 생각할 것이다 :

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

좀 더 명확 할 것입니다.


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

C #의 2 개의 보수 ~0 == -1로 인해 이진 표현에서 모든 비트가 1 인 숫자입니다.


그것보다 낫다

All = Cash | Check | CreditCard

나중에 다른 방법을 추가하면 다음과 같이 말합니다.

PayPal = 8 ,

당신은 이미 물결표로 끝났지 만, 모든 줄을 다른 줄로 바꿔야합니다. 나중에 오류가 발생하기 쉽습니다.

문안 인사


사용시 참고 사항

All = Cash | Check | CreditCard

모든 값을 포함하면서 모든 값과 같지 않은 다른 값 (-1)으로 Cash | Check | CreditCard평가하거나 평가 All하지 않는 추가 이점이 있습니다. 예를 들어 UI에서 3 개의 확인란을 사용하는 경우

[] Cash
[] Check
[] CreditCard

그 값을 합산하면 사용자가 모든 값을 선택 All하면 결과 열거 형에 표시됩니다.


For others who found this question illuminating, I have a quick ~ example to share. The following snippet from the implementation of a paint method, as detailed in this Mono documentation, uses ~ to great effect:

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

Without the ~ operator, the code would probably look something like this:

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

... because the enumeration looks like this:

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
}

Notice this enum's similarity to Sean Bright's answer?

I think the most important take away for me is that ~ is the same operator in an enum as it is in a normal line of code.


It's a complement operator, Here is an article i often refer to for bitwise operators

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

Also msdn uses it in their enums article which demonstrates it use better

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


The alternative I personally use, which does the same thing than @Sean Bright's answer but looks better to me, is this one:

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

Notice how the binary nature of those numbers, which are all powers of two, makes the following assertion true: (a + b + c) == (a | b | c). And IMHO, + looks better.


I have done some experimenting with the ~ and find it that it could have pitfalls. Consider this snippet for LINQPad which shows that the All enum value does not behave as expected when all values are ored together.

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 
}

Just want to add, if you use [Flags] enum, then it may be more convenient to use bitwise left shift operator, like this:

[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
}

참고URL : https://stackoverflow.com/questions/387424/what-is-the-tilde-in-the-enum-definition

반응형