Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 1개 있습니다.)
(시리즈 글이 5개 있습니다.)
.NET Framework: 673. C#에서 enum을 boxing 없이 int로 변환하기
; https://www.sysnet.pe.kr/2/0/11270

.NET Framework: 740. C#에서 enum을 boxing 없이 int로 변환하기 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/11506

.NET Framework: 779. C# 7.3에서 enum을 boxing 없이 int로 변환하기 - 세 번째 이야기
; https://www.sysnet.pe.kr/2/0/11565

.NET Framework: 1042. C# - enum 값을 int로 암시적(implicit) 형변환하는 방법?
; https://www.sysnet.pe.kr/2/0/12606

.NET Framework: 2131. C# - Source Generator로 해결하는 enum 박싱 문제
; https://www.sysnet.pe.kr/2/0/13384




C# - enum 값을 int로 암시적(implicit) 형변환하는 방법?

때로는 enum 값이 int로 암시적 형변환이 있었으면 좋을 때가 있습니다.

C# 7.3에서 enum을 boxing 없이 int로 변환하기 - 세 번째 이야기
; https://www.sysnet.pe.kr/2/0/11565

위의 박싱 문제 말고도 어떤 경우에는 다양한 enum 값을 받아야 할 수도 있는데요, 그럴 때 보통 int로 처리하게 됩니다.

using System;

class Program
{
    static void Main(string[] args)
    {
        PrintEnumValue((int)Project.Debug);
        PrintEnumValue((int)Solution.Project);
    }

    private static void PrintEnumValue(int value)
    {
        Console.WriteLine(value);
    }
}

enum Project
{
    Debug = 1,
    Release = 2,
}

enum Solution
{
    Project = 3,
    Item = 4,
}

보는 바와 같이, 매번 전달할 때 (int) 형변환하는 것이 꽤나 귀찮은 문제입니다. (좀 더 엄밀히 따지면, 이건 귀찮음의 문제가 아니라 개발자라는 직업의 성격상 뭔가,,, 마음속 깊이 받아들여지지 않는 무언가가 있습니다. ^^;)

어쩌면 이에 대한 이상적인 해결책은, 그러니까 기존 문법에 기반을 둬 추가한다면 enum 타입에서도 연산자 재정의를 지원하는 것입니다.

enum Project
{
    Debug = 1,
    Release = 2,

    // 지원하지 않는 문법: 컴파일 오류
    public static implicit operator int(Project value)
    {
        return (int)value;
    }
}

enum Solution
{
    Project = 3,
    Item = 4,

    // 지원하지 않는 문법: 컴파일 오류
    public static implicit operator int(Solution value)
    {
        return (int)value;
    }
}

보다시피, 지원하지 않는다는 것이 문제라서. ^^;




이에 대해 검색해 보면, 그나마 최선의 방법을 다음의 Q&A에서 보게 됩니다.

Can we define implicit conversions of enums in c#?
; https://stackoverflow.com/questions/261663/can-we-define-implicit-conversions-of-enums-in-c

덧글에 보면 중계 타입으로 PrimitiveEnum을 정의하고 있는데요,

McKabue.Extentions.Utility/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs
; https://github.com/McKabue/McKabue.Extentions.Utility/blob/master/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs

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

public class PrimitiveEnum
{
    private Enum _enum;

    public PrimitiveEnum(Enum _enum)
    {
        this._enum = _enum;
    }

    public Enum Enum => _enum;


    public static implicit operator PrimitiveEnum(Enum _enum)
    {
        return new PrimitiveEnum(_enum);
    }

    public static implicit operator Enum(PrimitiveEnum primitiveEnum)
    {
        return primitiveEnum.Enum;
    }

    public static implicit operator byte(PrimitiveEnum primitiveEnum)
    {
        return Convert.ToByte(primitiveEnum.Enum);
    }

    public static implicit operator sbyte(PrimitiveEnum primitiveEnum)
    {
        return Convert.ToSByte(primitiveEnum.Enum);
    }

    public static implicit operator short(PrimitiveEnum primitiveEnum)
    {
        return Convert.ToInt16(primitiveEnum.Enum);
    }

    public static implicit operator ushort(PrimitiveEnum primitiveEnum)
    {
        return Convert.ToUInt16(primitiveEnum.Enum);
    }

    public static implicit operator int(PrimitiveEnum primitiveEnum)
    {
        return Convert.ToInt32(primitiveEnum.Enum);
    }

    public static implicit operator uint(PrimitiveEnum primitiveEnum)
    {
        return Convert.ToUInt32(primitiveEnum.Enum);
    }

    public static implicit operator long(PrimitiveEnum primitiveEnum)
    {
        return Convert.ToInt64(primitiveEnum.Enum);
    }

    public static implicit operator ulong(PrimitiveEnum primitiveEnum)
    {
        return Convert.ToUInt64(primitiveEnum.Enum);
    }
}

이것을 이용하면 enum 타입을 쓰면서도 자연스럽게 int로 형변환하는 것이 가능합니다.

static void Main(string[] args)
{
    PrintEnumValue(Project.Debug);
    PrintEnumValue(Solution.Project);
}

/* 출력 결과
1
Debug
3
Project
*/

private static void PrintEnumValue(PrimitiveEnum value)
{
    int intValue = value; // 암시적 형변환 (박싱 발생)

    Console.WriteLine(intValue); // 출력: 정숫값
    Console.WriteLine(value.Enum); // 출력: enum 문자열
}

/*
private static void PrintEnumValue(Enum value)
{
    int intValue = Convert.ToInt32(value); // (박싱 발생)

    Console.WriteLine(intValue);    // 출력: 정숫값
    Console.WriteLine(value);       // 출력: enum 문자열
}
*/

현재로서는, 이 정도 수준이 최선일 듯합니다.

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 4/21/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2021-04-23 11시24분
[kernel] 새롭게 올려주신 글 덕분에 4년전 댓글 드렸던 글까지 다시 복기하게 되네요. 좋은 글 올려주셔서 항상 고맙습니다. :D
[guest]
2021-04-23 11시51분
@kernel 저도 가끔 그러면서 다시 "배웁니다." ^^;
정성태

... 121  122  123  124  [125]  126  127  128  129  130  131  132  133  134  135  ...
NoWriterDateCnt.TitleFile(s)
10891정성태2/16/201627826VC++: 95. 내 CPU가 MPX/SGX를 지원할까요? [1]
10890정성태2/15/201626371.NET Framework: 544. C# 5의 Caller Info를 .NET 4.5 미만의 응용 프로그램에 적용하는 방법 [5]
10889정성태2/14/201623552.NET Framework: 543. C++의 inline asm 사용을 .NET으로 포팅하는 방법 - 두 번째 이야기파일 다운로드1
10888정성태2/14/201621227.NET Framework: 542. 닷넷 - 특정 클래스가 로드되었는지 여부를 알 수 있을까?
10887정성태2/3/201623373VC++: 94. MPX(Memory Protection Extensions) 테스트파일 다운로드1
10886정성태2/3/201625085개발 환경 구성: 281. Intel MPX Runtime Driver 수동 설치
10885정성태2/2/201623353오류 유형: 317. Sybase.Data.AseClient.AseException: The command has timed out.
10884정성태1/11/201624115개발 환경 구성: 280. 닷넷에서 SAP Adaptive Server Enterprise 데이터베이스 사용파일 다운로드1
10882정성태1/6/201625007Windows: 113. 윈도우의 2179, 26143, 47001 TCP 포트 사용 [1]
10881정성태1/3/201625657오류 유형: 316. 윈도우 10 - 바탕/돋음 체가 사라져 한글이 깨지는 현상 [2]
10880정성태12/16/201524386오류 유형: 315. 닷넷 프로파일러의 오류 코드 정보
10879정성태12/16/201526156오류 유형: 314. Error : DEP0700 : Registration of the app failed. error 0x80070005
10878정성태12/9/201529594디버깅 기술: 75. UWP(유니버설 윈도우 플랫폼) 앱에서 global::System.Diagnostics.Debugger.Break 예외 발생 시 대응 방법
10877정성태12/9/201533163VC++: 93. std::thread 사용 시 R6010 오류 [2]
10876정성태11/26/201529127.NET Framework: 541. SignedXml을 이용한 ds:Signature만드는 방법 [3]파일 다운로드1
10875정성태11/26/201534626개발 환경 구성: 279. signtool.exe의 다중 서명 기능 [2]
10874정성태11/26/201529937개발 환경 구성: 278. 인증서와 인증서를 이용한 코드 사인의 해시 구분
10873정성태11/25/201528022.NET Framework: 540. C# - 부동 소수 계산 왜 이렇게 나오죠? (2) [3]파일 다운로드1
10872정성태11/24/201537380.NET Framework: 539. C# - 부동 소수 계산 왜 이렇게 나오죠? (1) [1]
10871정성태11/23/201530639오류 유형: 313. SignTool Error: No certificates were found that met all the given criteria.
10870정성태11/23/201532312오류 유형: 312. 윈도우 10 TH2 (버전 1511) 업데이트가 안되는 경우 [1]
10869정성태11/23/201528819오류 유형: 311. certutil 실행 오류 - 0x80070057 [1]
10868정성태11/20/201527751제니퍼 .NET: 25. 제니퍼 닷넷 적용 사례 (5) - RestSharp 라이브러리의 CPU High 현상파일 다운로드1
10867정성태10/18/201531878.NET Framework: 538. Thread.Abort로 인해 프로세스가 종료되는 현상
10866정성태10/14/201525682.NET Framework: 537. C# - Reflection의 박싱 없이 값 형식을 다루는 방법파일 다운로드1
10865정성태10/13/201526480.NET Framework: 536. Thread.Abort의 스레드 종료 지연파일 다운로드1
... 121  122  123  124  [125]  126  127  128  129  130  131  132  133  134  135  ...