OR 열거 형 항목을 제거하는 방법?


181

나는 열거 형이있다 :

public enum Blah
{
    RED = 2,
    BLUE = 4,
    GREEN = 8,
    YELLOW = 16
}

Blah colors = Blah.RED | Blah.BLUE | Blah.YELLOW;

가변 색상에서 파란색을 어떻게 제거합니까?


2
작은 메모 : C #의 비트 열거 형은 그 위에 [Flags] 특성을 가져와야합니다.
Nyerguds

@ Nyerguds, 왜 속성을 가져와야하는지 설명 할 수 있습니까?
ethane

알 수없는 열거 형 값을 기존 값의 조합으로 인식하므로 디버깅하는 동안 IntelliSense 지원이 향상됩니다.
Nyerguds

1
또한보다 의미있는 .ToString()가치를 제공 합니다. 예를 들어 RED, BLUE, YELLOW오히려 22.
Sinjai

답변:


331

'BLUE' &~(보완)로 해야합니다 .

보수 연산자는 기본적으로 주어진 데이터 유형에 대한 모든 비트를 반전 시키거나 '플립'합니다. 따라서 AND연산자 ( &)를 일부 값 (값을 'X'라고 함)과 하나 이상의 세트 비트의 보수 (그 비트 Q와 보수를 호출하자 ~Q)와 함께 사용하면 명령문 X & ~Q은 설정된 비트를 지 웁니다. Qfrom X및 결과를 반환합니다.

따라서 BLUE비트 를 제거하거나 지우 려면 다음 명령문을 사용하십시오.

colorsWithoutBlue = colors & ~Blah.BLUE
colors &= ~Blah.BLUE // This one removes the bit from 'colors' itself

다음과 같이 여러 비트를 지울 수 있습니다.

colorsWithoutBlueOrRed = colors & ~(Blah.BLUE | Blah.RED)
colors &= ~(Blah.BLUE | Blah.RED) // This one removes both bits from 'colors' itself

또는 교대로 ...

colorsWithoutBlueOrRed = colors & ~Blah.BLUE & ~Blah.RED
colors &= ~Blah.BLUE & ~Blah.RED // This one removes both bits from 'colors' itself

요약하면 다음과 같습니다.

  • X | Q 비트를 설정 Q
  • X & ~Q 비트를 지 웁니다 Q
  • ~X 모든 비트를 뒤집거나 뒤집습니다. X

1
따라서 더 많은 것을 제거하려면 다음과 같이하십시오. & = ~ Blah.BLUE & ~ Blah.Green?
Blankman

11
더 나은입니다colors &= ~( Blah.BLUE | Blah.GREEN );

2
얼마나 특이한 지, 나는 단지 약 5 일 전에이 작업을 다시 수행하는 방법을 생각하고있었습니다. :)이 질문은 내받은 편지함과 짜잔에서 업데이트되었습니다!
Blankman

좋은 대답입니다. 하지만 당신은 코드 샘플에서 "& ="not "= &"을 의미한다고 생각합니다.;)
Dave Jellison

48

다른 답변은 정확하지만 위의 파란색을 구체적으로 제거하려면 다음과 같이 작성하십시오.

colors &= ~Blah.BLUE;


7

이것은 나처럼 여기에서 우연히 발견 된 다른 사람들에게 유용 할 것이라고 생각했습니다.

값 == 0으로 설정 될 수있는 열거 형 값을 처리하는 방법에주의하십시오 (때로는 열거 형에 대해 알 수 없음 또는 유휴 상태를 유지하는 것이 도움이 될 수 있음). 이러한 비트 조작 작업에 의존 할 때 문제가 발생합니다.

또한 2의 다른 거듭 제곱의 조합 인 열거 형 값이있는 경우 (예 :

public enum Colour
{
    None = 0,  // default value
    RED = 2,
    BLUE = 4,
    GREEN = 8,
    YELLOW = 16,
    Orange = 18  // Combined value of RED and YELLOW
}

이러한 경우 다음과 같은 확장 방법이 유용 할 수 있습니다.

public static Colour UnSet(this Colour states, Colour state)
{
    if ((int)states == 0)
        return states;

    if (states == state)
        return Colour.None;

    return states & ~state;
}

또한 결합 된 값을 처리하는 동등한 IsSet 메소드도 있습니다 (약간 해키 방식이지만)

public static bool IsSet(this Colour states, Colour state)
{
    // By default if not OR'd
    if (states == state)
        return true;

    // Combined: One or more bits need to be set
    if( state == Colour.Orange )
        return 0 != (int)(states & state);

    // Non-combined: all bits need to be set
    return (states & state) == state;
}

더 간단한 해결책은 0을 플래그로 사용하지 않는 것 같습니다. 나는 일반적으로 같은 플래그 열거 설정 . 값이 0 인 상태를 지정하면 어떤 이점이 있는지 알 수 없습니다. 결국 요점은 Red, Blue, Green기본 값이 아닌 프로그래머에게 친숙한 이름 ( )에 관심을 가질 수 있다는 것입니다 .
Sinjai

갖는 none이나 unknown또는 unset값 == 0 항목이 많은 경우에 당신은 항상 당신은 레드, 블루와 그린은 당신이로 레드를 가지고가는 경우 특정 값이 기본 설정, 예를 있다고 가정 할 수 없기 때문에 좋은 것 기본값 (예를 들어 열거 형을 만들거나 사용자가이를 수정하지 않은 경우의 값)
Sverrir Sigmundarson

Unset = 1 만 있고 1, 2, 4, 8값으로 사용할 수 없습니까? 기본값이 필요한 경우 기본 생성자가 무엇입니까? 나는 가독성을 위해 가능한 한 명시 적으로 유지하고 싶습니다 . 값이 주어지지 않을 때 기본값으로 열거에 의존하는 것은 default(int)( 0)입니다. 어떤 개발자가 아마 알고있는 정보 임에도 불구하고 어쨌든 내 취향으로는 너무 열악합니다. 편집 : 아 잠깐, Unset = 0으로 만들면 무언가가 방해받지 Unset | Blue않습니까?
Sinjai

당신은 편집 Sinjai의 올바른 길을 가고 있습니다. 설정되지 않은 값 == 0을 유지하면 실제로 몇 가지 문제가 해결됩니다. 하나는 언급 한 것이고 다른 하나는 모든 열거 값을 설정 해제하면 "설정되지 않음"이 0으로 설정된 경우 특별한 경우가 필요하지 않습니다. (예를 들어, Red & ~Red0으로 끝나는 경우에는이 경우를 확인하고 명시 적으로 Unset값을 할당하는 코드가 있어야 합니다)
Sverrir Sigmundarson

알았어 자주 설정되지 않은 플래그를 다루고 있습니까?
Sinjai

2

xor (^)는 어떻습니까?

제거하려는 플래그가 있으면 작동합니다. 그렇지 않은 경우 &를 사용해야합니다.

public enum Colour
{
    None = 0,  // default value
    RED = 2,
    BLUE = 4,
    GREEN = 8,
    YELLOW = 16,
    Orange = 18  // Combined value of RED and YELLOW
}

colors = (colors ^ Colour.RED) & colors;

1

플래그 열거를 단순화하고 배수를 피함으로써 읽는 것이 더 나을 수 있도록 비트 이동을 사용할 수 있습니다. (좋은 기사 에서 열거 형 깃발에 대한 대 쟁투 끝내기 )

[FLAG]
Enum Blah
{
   RED = 1,
   BLUE = 1 << 1,
   GREEN = 1 << 2,
   YELLOW = 1 << 3
}

또한 모든 비트를 지우려면

private static void ClearAllBits()
{
    colors = colors & ~colors;
}

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