2011-03-12 4 views
15

-= 연산자가 enum 값에서 지원되는지 (그리고 그 이후부터) 알 수 있습니까? 내가 어떤 이유로, 이것은 플래그 enum에서 값을 제외 쓴열거 및 빼기 연산자

내가 행복하게 오늘을 멀리 코딩 된 : 다시 읽고 내 코드를 평가 한 후

flags -= FlagsEnum.Value1; 

, 나는 그것이 실제로 일을 컴파일 된 것을 놀랐습니다 .

flags = flags - FlagsEnum.Value1 

로 문을 작성하지만 하지 컴파일을 수행합니다.

설명서 및 인터넷에서 지금까지 아무 것도 찾을 수 없었습니다. 또한 다른 연산자 (물론 비트 연산자 제외)는 지원되지 않습니다. += (플래그 포함), *= (파스칼의 교집합)이 작동하지 않습니다.

이것은 C# 컴파일러에 내장 된 구문 설탕입니까? 그렇다면 다른 사업자를 포함시키지 않는 이유는 무엇입니까?

간단한 코드 샘플 :

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication4 
{ 
    [Flags] 
    enum FlagsEnum 
    { 
     None = 0, 
     Value1 = 1, 
     Value2 = 2, 
     Value3 = 4 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      FlagsEnum flags = FlagsEnum.Value1 | FlagsEnum.Value2 | FlagsEnum.Value3; 
      Console.WriteLine(flags); 
      flags -= FlagsEnum.Value1; 
      Console.WriteLine(flags); 
      flags -= FlagsEnum.Value3; 
      Console.WriteLine(flags); 
      flags -= FlagsEnum.Value2; 
      Console.WriteLine(flags); 
      Console.ReadLine(); 
     } 
    } 
} 
+0

실제로 작동하는지 확인하십시오. 당신은 뺄셈이 그 비트를 배제하는 것처럼 보일 것이라는 사실에기만 당할 수 있습니다. Value1에 해당하는 비트가 이미 0 인 플래그 변수에서 시도 했습니까? – Tormod

+0

그런 식으로 사용하면 꽤 안전하지 않습니다. 'FlagsEnum.Value1'이 이미'flags'에 들어있을 때만 enum으로 동작합니다. –

+0

@Jaroslav : 나는 그것을 결코 그렇게하지 않는다. 그러나 그것은 단지 나의 손가락에서 굴러 떨어지게되었다.델파이 (좋은 집합 연산자가있는)에 그것을 비난했지만, 꽤 작았지만 (현재는 적지 만) 컴파일 된 것이 놀랍습니다. 그리고 Marc이 지적했듯이, 그 결과는 당신이 기대하는 것과 다를 수도 있습니다. –

답변

6

열거 공제. 모든 열거 형은 암시 적으로 다음과 같은 미리 정의 된 연산자를 제공합니다. 여기서 E는 열거 형이고 U는 기본 형식 인 E입니다. U 연산자 - (E x, E y); 이 연산자는 (U) ((U) x - (U) y)와 정확하게 동일하게 평가됩니다. 즉 연산자는 x와 y의 서수 값 사이의 차이를 계산하고 결과 유형은 열거 형의 기본 유형입니다.

source

난 당신이 열거 회원에 대한 암시 적 값을 정의 할 수 있다는 것을 알고 희망, 그래서 당신은 그들에게 값 X = 5를 주면, 당신을 Y는 Z = 15 10 = 당신은 ZY을하려고합니다 x를 얻을 것이다.

+0

Aaah ... 사양. :) 내가 보지 않은 유일한 곳 (그리고 솔직히 말해서 거의 보지 않는 곳). 감사. 열거 형에 대해 + = 연산자가 비슷한 방식으로 정의되지 않은 이유는 무엇입니까? –

+0

음, 나는 아직도'E - = E'가 어떻게 컴파일되는지,'E = E - E'가 이해하지 못한다 ... – digEmAll

+0

@digEmAll : Darn ... 여전히 수수께끼로 남아있다 ... –

21

Iirc, -은 여전히 ​​정수 빼기입니다.

이 배제하려면 원하는 :

value = value & ~SomeEnum.Flag; 

그리고 포함 : 부분 일치를 테스트하기 위해 마찬가지로

value = value | SomeEnum.Flag; 

, (깃발에서 어떤 비트) :

if((value & SomeEnum.Flag) != 0) {...} 

또는 전체 경기 (깃발의 모든 비트) :

if((value & SomeEnum.Flag) == SomeEnum.Flag) {...} 
+1

누가 이것을 내렸습니까? '& (~ flag)'는 플래그를 제거하는 올바른 기술이다. (플래그)'를 추가하고 '&'는 교차로를 추가합니다. –

+0

예, "정상적인"방법입니다. 그러므로 내 질문. –

+0

@Marc : 열거 형이 어떻게 작동하는지 알고 있습니다. 그래서 내가 처음에 질문을 던졌습니다. –