본문 바로가기
C#

[C#] 열거형과 System.Enum

by DANEW 2023. 8. 21.

열거형과 System.Enum 

 

Enum 클래스 (System)

열거형에 대한 기본 클래스를 제공합니다.

learn.microsoft.com

- .NET Framework는 열거형에 대한 C#의 지원을 System.Enum 형식을 통해 확장함

 * 모든 enum 형식을 통합(Type Unification)하는 기준 - 임의의 열거형 멤버를 System.Enum의 인스턴스로 암묵적 변환 가능

 * 편의용 정적 메서드들을 정의

 

열거형의 변환

1. 열거형 멤버를 정수로 변환

 - enum 형식의 한 멤버와, 해당 정수 값 사이의 변환에서는 명시적 캐스팅이 필요함

 - System.Enum 인스턴스도 마찬가지로 명시적 캐스팅이 필요함

 

 a. casting

  - object형으로 캐스팅 후, 해당 정수 형식으로 다시 캐스팅 (ex: (int) (object) anyEnum)

  - 해당 정수 형식을 프로그래머가 알고 있어야 한다는 단점이 있음. (int형식인데 short, long을 쓰면 컴파일 에러)

 

 b. decimal을 이용

  - Convert.ToDecimal을 이용

  - 모든 정수 형식(unsigned도)을 정보의 손실 없이 decimal로 바꿀 수 있는 것을 이용함

  - 정수 형식을 몰라도 됨. 단, 원래의 정수 형식이 보존되지 않고, decimal로 바뀌게 됨

 

 c. Enum.GetUnderlyingType, Convert.ChangeType

  - Enum.GetUnderlyingType을 통하여 해당 enum의 형식을 받아옴

  - 해당 enum의 형식에 맞게 Convert.ChangeType으로 타입을 바꿔줌.

  - 정수 형식을 몰라도 되고, 원래의 정수 형식을 보존 할 수 있음

  - 실제로는 값 변환을 수행하진 않음. 같은 값을 다른 형식으로 다시 박싱하는 것.

 

 d. 서식 문자열

  - Format이나 ToString에 "d", "D"를 지정해서 호출

  - enum의 정수 값을 표현한 문자열이 반환됨

  - 정수 형식을 몰라도 됨. 단, 원래의 정수 형식이 보존되지 않고, string으로 바뀌게 됨

  - 커스텀 직렬화 서식화 클래스를 작성할 때 유용

 

2. 정수를 열거형으로 변환

 a. 정적 변환

  - 명시적 캐스트

 

 b. 동적 변환

  - Enum.ToObject: 정수 값을 주어진 enum 형식의 인스턴스로 변환

반응형

3. 열거형을 문자열로 변환

 - Enum.Format, ToString

 - G: 표준적인 표현

 - D: 바탕 정수값을 표현하는 문자열

 - X: 십육진수 표현

 - F: Flags 특성이 지정되지 않았더라도 조합된 멤버의 구성 멤버 나열

 

4. 문자열을 열거형으로 변환

 - Enum.Parse

 - Enum 형식, 멤버 이름(들)이 나열된 문자열, 대소문자 구분 여부(생략 가능)

 

열거형 값들의 열거(나열)

- Enum.GetValues: 모든 멤버를 담은 배열을 돌려줌

- Enum.GetNames: 모든 멤버를 담은 문자열 배열을 돌려줌

- 결과에는 조합된 멤버들도 포함

 

열거형의 작동 방식

- CLR에서 enum은 그냥 System.Enum의 각 멤버마다 정수 형식 정적 필드가 하나 있는 한 하위 형식으로 정의

- 정수처럼 취급되기에 실행시점 비용이 정수 상수에 비견할 정도로 적음

- 정적 형식 안정성을 제공하진 하지만, 강한 형식 안정성은 제공하지 못함. 컴파일러가 열거형 연산의 유효성을 검증하지 못함.

- ToString, GetType같은 메서드가 호출되면 enum의 인스턴스를 enum 형식에 관한 정보를 담아(정수가 아닌) 박싱해서 보내줌

using System;
 
namespace Practice
{
    class Program
    {
        [Flags] enum BorderSides { Left = 1, Right = 2, Top = 4, Bottom = 8 }
 
        static void Main(string[] args)
        {                      
            // 형식 통합
            Nut.Display(Nut.Name.Macadamia);
            Nut.Display(Nut.Size.Large);
            Console.WriteLine();
 
 
            // 열거형 멤버를 정수로 변환
            // enum 형식
            int i = (int)BorderSides.Top;
            BorderSides side = (BorderSides) i;
            DisplayType(i);
            DisplayType(side);
            Console.WriteLine();
 
            // a. casting
            DisplayType(EnumCoverter.GetIntegralValue(side));
 
            // b. decimal을 이용
            DisplayType(EnumCoverter.GetAnyIntegralValue(side));
 
            // c. Enum.GetUnderlyingType, Convert.ChangeType
            DisplayType(EnumCoverter.GetBoxedIntegralValue(side));
 
            // d. 서식 문자열
            DisplayType(EnumCoverter.GetIntegralValueAsString(side));
            Console.WriteLine();
 
 
            // 정수를 열거형으로 변환
            // a. 정적 변환
            Console.WriteLine((BorderSides)3);
 
            // b. 동적 변환
            Console.WriteLine(Enum.ToObject(typeof(BorderSides), 3));
            Console.WriteLine();
 
 
            // 열거형을 문자열로 변환
            string[] strForEnum = "G g X x F f D d".Split(' ');
 
            foreach (var item in strForEnum)
            {
                Console.WriteLine($"{item}: {side.ToString(item)}");
            }
            Console.WriteLine();
 
 
            // 문자열을 열거형으로 변환
            BorderSides LR = (BorderSides)Enum.Parse(typeof(BorderSides), "Left, Right");
            Console.WriteLine(LR);
            Console.WriteLine();
 
 
            // 열거형 값들의 열거(나열)
            foreach (var item in Enum.GetValues(typeof(BorderSides)))
            {
                DisplayType(item);
            }
            Console.WriteLine();
 
            foreach (var item in Enum.GetNames(typeof(BorderSides)))
            {
                DisplayType(item);
            }
            Console.WriteLine();
        }
 
        static void DisplayType(object item)
        {
            Console.WriteLine($"{item.GetType()}, {item}");
        }
 
        static class Nut
        {
            public enum Name { Walnut, Hazelnut, Macadamia }
            public enum Size { Small, Medium, Large }
 
            public static void Display(Enum value)
            {
                Console.WriteLine(value.GetType().Name + "." + value.ToString());
            }
        }
 
        static class EnumCoverter
        {
            public static int GetIntegralValue(Enum anyEnum)
            {
                return (int)(object)anyEnum;
            }
 
            public static decimal GetAnyIntegralValue(Enum anyEnum)
            {
                return Convert.ToDecimal(anyEnum);
            }
 
            public static object GetBoxedIntegralValue(Enum anyEnum)
            {
                Type integralType = Enum.GetUnderlyingType(anyEnum.GetType());
                return Convert.ChangeType(anyEnum, integralType);
            }
 
            public static string GetIntegralValueAsString(Enum anyEnum)
            {
                return anyEnum.ToString("D");
            }
        }
    }
}

 

 

 

반응형

'C#' 카테고리의 다른 글

[C#] 상등 비교 (IEquatable<T>)  (0) 2023.08.25
[C#] Guid  (0) 2023.08.24
[C#] Math  (1) 2023.08.23
[C#] Tuple  (1) 2023.08.22
[C#] Random & RandomNumberGenerator  (1) 2023.08.20
[C#] Complex  (1) 2023.08.19
[C#] BigInteger  (1) 2023.08.18
[C#] BitConverter  (1) 2023.08.17