열거형과 System.Enum
- .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 |