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


149

나는 지금까지 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
}

나는 그것을 보려고 조금 놀랐다. 그래서 그것을 컴파일하려고 시도했지만 효과가 있었다. 어떤 도움?


4
이것은 시간이 지남에 따라 열거를 부드럽게 업그레이드 할 수있는 훌륭하고 우아한 솔루션입니다. 불행히도 CA-2217과 충돌하고 코드 분석 :( 사용할 경우 오류가 발생합니다 msdn.microsoft.com/en-us/library/ms182335.aspx
제이슨 코인

이제 2020 년이되었는데 게시물을 시작하는 단어와 같은 단어를 생각하고 있습니다. 내가 혼자가 아니라는 것이 기쁘다.
funkymushroom

답변:


136

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

~0 = 0xFFFFFFFF = -1

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

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


멋지다. 나는 당신이 열거 형에서 그렇게 할 수 있다는 것을 몰랐습니다. 확실히 미래에 사용합니다
오리온 에드워즈에게

따라서 All = Int32.MaxValue와 같습니다. 또는 UInt32.MaxValue?
Joel Mueller

2
모두 = (부호없는 정수) -1 == UInt32.MaxValue. Int32.MaxValue는 관련이 없습니다.
Jimmy

4
@ Stevo3000 : Int32.MinValue는 0xF0000000이며 ~ 0이 아닙니다 (실제로 ~ Int32.MaxValue 임)
Jimmy

2
@ Jimim : Int32.MinValue는 0x80000000입니다. 단일 비트 세트 만 있습니다 (F가 제공하는 4 개는 아님).
ILMTitan

59

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

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

좀 더 명확 할 것입니다.


10
확실합니다. 단항의 유일한 좋은 효과는 누군가가 열거에 추가하면 모두 자동으로 포함한다는 것입니다. 그럼에도 불구하고 그 이점은 명확성의 부족보다 중요하지 않습니다.
ctacke

12
나는 그것이 더 명확한 방법을 보지 못합니다. "모두"는 "정확하게이 3 개 세트"또는 "이 열거 형의 모든 것"을 의미합니까? 새 값을 추가하면 All에도 추가해야합니까? 다른 사람 All에 새로운 가치를 부여 하지 않은 것을 본다면 의도적 인 것입니까? ~ 0은 명시 적입니다.
Ken

16
개인적인 취향을 제외하고, ~ 0의 의미가 당신과 나만큼 OP에 분명하다면, 그는 결코이 질문을 처음부터 제기하지 않았을 것입니다. 한 접근 방식과 다른 접근 방식의 명확성에 대해 무엇을 말하는지 잘 모르겠습니다.
Sean Bright

9
C #을 사용하는 일부 프로그래머는 아직 <<의 의미를 알지 못할 수 있으므로 더 명확하게 코드를 작성해야합니까? 나는 그렇게 생각하지 않는다.
커트 콜러

4
@Paul, 그건 미친 짓이야. 사용을 중지합시다; 많은 사람들이 그것의 사용을 이해하지 못하기 때문에 영어로. 또는 그들이 모르는 모든 단어. 와우, 그런 작은 연산자 세트, 그리고 비트가 무엇인지 모르고 조작하는 방법을 모르는 사람들을 위해 코드를 바보로 만들어야합니까?
커트 콜러

22
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 인 숫자입니다.


결제 수단에 대한 비트 플래그를 만드는 것 같습니다. 000 = 없음; 001 = 현금; 010 = 점검; 100 = 신용 카드; 111 = 모두
Dillie-O

2의 보수는 아니고, 모든 비트를 반전시키고 1을 더하여 2의 보수는 여전히 0입니다. ~ 0은 단순히 모든 비트 또는 1의 보수를 반전시킵니다.
Beardo

아니요, 2의 보수는 단순히 모든 비트를 반전시킵니다.
구성자

2
@configurator-맞지 않습니다. 그것들의 보완은 간단한 비트 반전입니다.
Dave Markle

c #은 두 개의 보수를 사용하여 음수 값을 나타냅니다. 물론 ~는 두 개의 보수가 아니라 단순히 모든 비트를 반전시킵니다. 어디에서 구했는지 잘 모르겠습니다. Beardo
Johannes Schaub-litb

17

그것보다 낫다

All = Cash | Check | CreditCard

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

PayPal = 8 ,

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

문안 인사


왜 오류가 적은 이유를 말하는 것이 좋습니다. 예를 들어, 데이터베이스 / 이진 파일에 값을 저장 한 다음 열거에 다른 플래그를 추가하면 'All'에 포함됩니다. 즉, 'All'은 플래그는 동일합니다 :).
Aidiakapi

11

사용시 참고 사항

All = Cash | Check | CreditCard

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

[] Cash
[] Check
[] CreditCard

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


그래서 당신이 myEnum.HasFlag()대신 사용 하는 이유 : D
Pyritie

@Pyritie : 귀하의 의견은 내가 한 말과 어떤 관련이 있습니까?
구성자

에서와 같이 ... "All"에 ~ 0을 사용하면 비슷한 작업을 수행 할 수 All.HasFlag(Cash | Check | CreditCard)있습니다. ==~ 0에서 항상 작동하지는 않으므로 해결 방법이 될 것 입니다.
Pyritie

아, 디버거와 함께 표시되는 내용에 대해 이야기했다 ToString하지 사용하는 방법에 대해 - == All.
구성자

9

이 질문을 밝히는 다른 사람들을 위해, 나는 ~공유 할 빠른 예가 있습니다. 에 설명 된대로 페인트 메소드의 구현에서 다음 코드는 이 모노 문서 , 사용하는 ~큰 효과를 :

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

~연산자가 없으면 코드는 다음과 같이 보일 것입니다.

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

... 열거 형이 다음과 같기 때문에 :

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
}

이 열거 형이 Sean Bright의 답변과 유사합니까?

필자가 가장 중요하게 생각하는 것은 ~일반적인 코드 줄과 동일한 열거 형 연산자입니다.


두 번째 코드 블록에서 &s 는 아니어야 |합니까?
ClickRick

@ClickRick, 캐치 주셔서 감사합니다. 두 번째 코드 블록은 실제로 의미가 있습니다.
Mike


1

@ 개인적으로 사용하는 대안은 @Sean Bright의 답변과 동일한 기능을하지만 나에게 더 좋아 보입니다.

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

이 2의 거듭 제곱 인 숫자의 이진 특성으로 인해 다음과 같은 주장이 어떻게 적용되는지 확인하십시오 (a + b + c) == (a | b | c). 그리고 IMHO, +더 좋아 보인다.


1

~로 실험을 해본 결과 함정이있을 수 있음을 알았습니다. 모든 값이 함께 정렬 될 때 All 열거 형 값이 예상대로 작동하지 않음을 보여주는 LINQPad에 대한이 스 니펫을 고려하십시오.

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 
}

표준은 0 값을
가져서는 안되지만

0

[Flags] 열거 형을 사용하는 경우 다음과 같이 비트 왼쪽 시프트 연산자를 사용하는 것이 더 편리 할 수 ​​있습니다.

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

이것은 전혀 질문에 대답하지 않습니다.
봉사
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.