OR 연산으로 조립이 가능한 옵션 매개 변수 만들기

아주 유용한 프로그래밍 기술을 하나 소개하도록 하겠습니다. 흔히 C/C++에서 사용되던 방법으로 몇 개의 수를 OR 연산으로 조합하여 하나의 매개 변수로 여러개의 의미를 해석하도록 매개 변수를 전달하는 방법입니다. 이것을 사용하면 오버로드를 최소화하면서 필요한 옵션 전달이 모두 가능하도록 메서드를 설계할 수 있습니다. 이것을 상수로 정의하여 전달할 수도 있지만 좀 더 세련되고 쓰기 쉬운 방법으로 나열 상수를 활용해보도록 합시다.



    [Flags()]


    [Serializable()]


    public enum Colors : int


    {


      None = 0,


      Red = 1,


      Green = Red * 2,


      Blue = Green * 2


    }


나열 상수의 값을 2의 배수 간격으로 띄웠습니다. 이것은 중/고등학교 수학 시간에 배웠던 “조합 (Combination)”이라는 수학적 원리에 기초합니다. 나올 수 있는 경우의 수를 살펴보도록 하지요.



  • 0: 아무 것도 선택 안함
  • 1: 빨간색
  • 2: 녹색
  • 3: 빨간색 + 녹색
  • 4: 파란색
  • 5: 빨간색 + 파란색
  • 6: 녹색 + 파란색
  • 7: 빨간색 + 녹색 + 파란색

유추된 경우의 수를 모두 세어보면 8가지입니다. 아무 것도 선택하지 않을 수도 있고, 적어도 1가지는 선택할 수도 있고, 2가지를 선택할 수도 있으며, 모든 것을 다 선택할 수도 있는 것입니다. 이러한 개념에 비추어 볼 때, 0은 아무 것도 조합하지 않았음을 의미합니다. 하지만 0보다 큰 1 이상의 모든 숫자들은 조합으로 나올 수 있는 내용들입니다. 이것들에 대한 의미를 정확히 파악하고 switch/case 구문으로 처리한다면 아주 간단합니다.


수학적 원리는 살펴보았고, 프로그래머의 입장에서 문법이 무엇을 의미하는지를 살펴볼 차례가 남았습니다.


나열 상수의 선언문 앞에 붙는 두 가지 특성이 있는데, FlagsAttribute와 SerializableAttribute입니다. Flags 속성은 등장할 나열 상수가 OR 연산이 가능함을 선언합니다. 이것을 붙이지 않으면 OR 연산을 위하여 반드시 (int) 라는 캐스트 연산자를 붙여야 하는 불편함이 따릅니다. 그리고 Serializable 속성은 나열 상수에는 관습 상 붙이게 됩니다. 또한, int 라는 형식 지정을 하게 되었는데 이것은 각 값들이 System.Int32의 값으로 캐스팅 될 수 있음을 약속하는 사항입니다.


그렇다면 옵션이 추가될 때 마다 특정 옵션이 정확하게 선택이 되었는지를 어떻게 확인할 수 있을까요? 사용자가 항목 선택을 위하여 OR 연산을 수행하였듯이 그 반대의 연산인 AND 연산을 수행하면 플래그의 수가 아무리 많더라도 플래그의 수 – 혹은 – 필요한 수 만큼 비교할 수 있습니다.

다음의 코드를 살펴보도록 합니다.

Colors nColors = Colors.Red | Colors.Blue;

if((nColors & Colors.Red) != Colors.None)
  Console.WriteLine(“Red Selected.”);

if((nColors & Colors.Blue) != Colors.None)
  Console.WriteLine(“Blue Selected.”);

if((nColors & Colors.Green) != Colors.None)
  Console.WriteLine(“Green Selected.”);


위의 코드를 실행하면 Red와 Blue가 선택되었음을 알리는 메시지가 콘솔 화면에 나타납니다. & 연산자를 이용하여 AND 연산을 수행하였을 때 특정 플래그가 선택되지 않았다면 0에 해당하는 값이 결과 값으로 나오게 되는 점을 이용한 것입니다.

많은 도움 되셨기를 바랍니다. 🙂

댓글 남기기