![[C#] 여러개의 Enum - [Flags] Attribute](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLsb62%2FbtsvlzSoTG6%2Fbo5IFIocgY6GbvRd3NUNX1%2Fimg.png)
우리는 Enum 타입으로 여러가지 상태나 상황을 정할 수 있다.
Enum을 조금 더 효과적으로 사용하기 위한 Flags 애트리뷰트를 공부해봤다.
Flags
Flags는 Enum타입에 사용되는 애트리뷰트이고,
열거형 멤버들이 비트 플래그로 사용될 수 있음을 나타낸다.
메모리가 중요했던 옛날에는 기껏해야 10개도 안되는 상태를 표현하려고 한 바이트(2^8 = 0~255)를 사용한다는게 낭비라고 생각이 됐을 수도 있다.
물론 지금은 메모리가 풍족해진 상황이지만, 비트 플래그가 갖는 장점도 있기 때문에 C#에서도 사용이 가능하게끔 구현을 해둔 것 같다.
선언
Enum 상단에 [Flags]라는 애트리뷰트를 선언해주면 된다.
그리고 Enum의 멤버들은 10진수로 적어줘도 상관없지만, 2의 제곱수로 적어주어야 한다.
계산하면서 적기 귀찮으니 비트연산 중 왼쪽 시프트 연산으로 적어 주었다.
[Flags]의 장점 - 여러 상태를 한번에
[Flags] 애트리뷰트를 선언한 Enum의 장점이라고 한다면 , 여러가지 상태를 한번에 가질 수 있다는 점이다.
위의 State값을 예로 들자면 , Idle 상태에서 Happy나 Hungry상태가 같이 있을수도 있다.
public State state = State.Idle;
void Start()
{
//2가지의 상태
state = State.Idle | State.Hungry;
//상태 추가
state |= State.Happy;
}
비트 or 연산을 통해 여러가지 상태를 한번에 변수에 넣어줄 수 있다.
Flags 애트리뷰트를 사용하면 유니티 인스펙터에서도 여러가지 값을 가질 수 있게 변경이 된다.
상태를 확인하기 위해서는 HasFlag를 사용하면 된다.
public void CheckState()
{
if (this.state.HasFlag(State.Idle))
{
Debug.Log("아이들 상태!");
}
if (this.state.HasFlag(State.Hungry))
{
Debug.Log("헝그리 상태!");
}
if (this.state.HasFlag(State.Fight))
{
Debug.Log("파이트 상태!");
}
}
이처럼 위에서 설정하지 않은 Fight 상태는 들어오지 않는다.
멤버의 값이 2의 제곱수여야 하는 이유
HasFlag를 사용하는 대신에, 아래 코드처럼 확인 할 수도 있다.
public void CheckState()
{
if ((this.state & State.Idle) != 0)
{
Debug.Log("아이들 상태!");
}
if ((this.state & State.Hungry) != 0)
{
Debug.Log("헝그리 상태!");
}
if ((this.state & State.Fight) != 0)
{
Debug.Log("파이트 상태!");
}
}
위 코드를 보면 왜 멤버들의 값이 2의 제곱수여야 하는지 알 수 있는데,
비트 And 연산을 통해 비트값이 하나라도 맞는다면 1, 아니면 0 이 나오기 때문에 어떤 상태를 가지고 있는지 알 수 있다.
하지만 예를들어서 Enum 멤버의 값이 순서대로 1,2,3이라고 정의 해보자.
Idle = 1 (2진수로 0001)
Hungry = 2 (2진수로 0010)
Fight = 3 (2진수로 0011)
이상태에서 Idle과 Hungry를 비트 or 연산을 한다면
0001
0010
--------
0011
Fight와 값이 똑같아 진다.
위 설명처럼 Enum값을 바꿔보았다.
public State state = State.Idle;
void Start()
{
state = State.Idle | State.Hungry;
CheckState();
}
public void CheckState()
{
if ((this.state & State.Idle) != 0)
{
Debug.Log("아이들 상태!");
}
if ((this.state & State.Hungry) != 0)
{
Debug.Log("헝그리 상태!");
}
if ((this.state & State.Fight) != 0)
{
Debug.Log("파이트 상태!");
}
}
상태에 Fight를 넣지 않았음에도 불구하고 파이트 상태도 같이 들어오는것을 볼 수 있다.
https://andromedarabbit.net/2008/08/08/csharp_flag_operations/
[C#] Flag 연산 총정리
C#의 Enum 타입에 대해 공부하려고 Enum values as bit flags - using FlagsAttribute을 읽다가 본문이 아닌 댓글에서 쓸만한 정보를 찾았다. Jeremy Lundy라는 사람이 Flag 연산에 대해 잘 정리해놨다. [Flags] public enu
andromedarabbit.net
위 사이트에 가보면 상태를 추가하고 빼는 등 비트연산을 이용하는 방법에 대해 잘 정리해 놓은 글이 있다.
혹시나 사용하게 된다면 참고하면 좋을 것 같다.
공부를 하면서 이것저것 얘기하긴 했지만, 다른것보다는 간단하게 여러 상태를 한번에 가지고 있을 수 있다는게 언젠가는 쓸 일이 많을것 같다는 생각이 들었다.
예를들면 가진 상태별로 특정 행동을 수행한다던지, 저장을할때 바뀐부분만 Enum 변수에 넣어서 전달해준다던지..
알아두면 좋을 것 같다!
'프로그래밍 공부 > C# 프로그래밍' 카테고리의 다른 글
[C#] 강력한 데이터 작업 Linq(링큐) (0) | 2023.09.24 |
---|---|
델리게이트와 이벤트(Delegate & Event) (1) | 2023.03.21 |
[C#] re-throw? 그리고 throw vs throw EX (2) | 2022.09.18 |
[C#] 예외처리 Try - Catch / Throw & Finally (0) | 2022.09.18 |
[C#] 프로퍼티란? & 자동구현 프로퍼티와 public 변수와의 차이 찾아보기 (0) | 2022.08.24 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!