Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)

닷넷 메타데이터에 struct/class(값/참조 형식)의 구분이 있을까요?

메타데이터 테이블로부터 타입에 대한 정보를 조회할 수 있는 메서드가 있습니다.

IMetaDataImport::GetTypeDefProps method
; https://learn.microsoft.com/en-us/windows/win32/api/rometadataapi/nf-rometadataapi-imetadataimport-gettypedefprops

HRESULT GetTypeDefProps(
  [in]                                               mdTypeDef tkTypeDef,
  [out, size_is(cchTypeDef), length_is(*pchTypeDef)] LPWSTR    szTypeDef,
  [in]                                               ULONG     cchTypeDef,
  [out]                                              ULONG     *pchTypeDef,
  [out]                                              DWORD     *pdwTypeDefFlags,
  [out]                                              mdToken   *ptkExtends
);

이 중에서 5번째 인자에 타입의 속성에 대한 정보를 받아올 수 있는데요.

CorTypeAttr Enumeration
; https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/metadata/cortypeattr-enumeration

위의 상수 표현을 보면 tdClass 속성이 있지만 값이 0x0이라서 (참조 형식의) 클래스만 그 값을 가지고 있는지 확인할 길이 없습니다. 즉, tdStruct 또는 tdValueType과 같은 이름의 상수값이 없는 것입니다.

재미있는 것은, .NET BCL의 Type 클래스에는 IsClass라는 속성으로 해당 타입의 값/참조 형식을 구분할 수 있는 기능이 제공된다는 점입니다. 그런데, 이 값을 구해오는 방법이 흥미롭습니다. .NET Reflector로 보면 다음과 같은데,

public bool IsClass
{
    get
    {
        return (((this.GetAttributeFlagsImpl() & TypeAttributes.ClassSemanticsMask) == TypeAttributes.AnsiClass) && !this.IsValueType);
    }
}

중요한 것은 IsValueType입니다. 그리고, 놀랍게도~~~ IsValueType의 구현은 '일반적인 상식(?)'을 벗어나는 방식으로 만들어졌습니다.

public bool IsValueType
{
    get
    {
        return this.IsValueTypeImpl();
    }
}
        
internal static readonly RuntimeType ValueType = ((RuntimeType) typeof(System.ValueType));

protected virtual bool IsValueTypeImpl()
{
    return this.IsSubclassOf(RuntimeType.ValueType);
}

public virtual bool IsSubclassOf(Type c)
{
    Type baseType = this;
    if (!(baseType == c))
    {
        while (baseType != null)
        {
            if (baseType == c)
            {
                return true;
            }
            baseType = baseType.BaseType;
        }
        return false;
    }
    return false;
}

그렇습니다. ^^ 특정 타입의 값/참조 형식을 알고 싶다면 이렇게 해당 클래스의 상위로 계속 찾아들어가 System.ValueType이 나올 때까지 탐색해 보는 것입니다.

결론을 내면, 메타데이터에는 Value/Reference 여부를 알 수 있는 정보는 저장되어 있지 않습니다.




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 7/3/2023]

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

비밀번호

댓글 작성자
 




... 46  47  48  49  [50]  51  52  53  54  55  56  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
12724정성태7/21/202119246개발 환경 구성: 582. 윈도우 환경에서 Visual Studio Code + Go (Zip) 개발 환경 [1]
12723정성태7/21/202115287오류 유형: 740. SharePoint - Alternate access mappings have not been configured 경고
12722정성태7/20/202115385오류 유형: 739. MSVCR110.dll이 없어 exe 실행이 안 되는 경우
12721정성태7/20/202121104오류 유형: 738. The trust relationship between this workstation and the primary domain failed. - 세 번째 이야기
12720정성태7/19/202116440Linux: 43. .NET Core/5+ 응용 프로그램의 Ubuntu (Debian) 패키지 준비
12719정성태7/19/202115441오류 유형: 737. SharePoint 설치 시 "0x800710D8 The object identifier does not represent a valid object." 오류 발생
12718정성태7/19/202115109개발 환경 구성: 581. Windows에서 WSL로 파일 복사 시 root 소유권으로 적용되는 문제파일 다운로드1
12717정성태7/18/202115690Windows: 195. robocopy에서 파일의 ADS(Alternate Data Stream) 정보 복사를 제외하는 방법
12716정성태7/17/202116140개발 환경 구성: 580. msbuild의 Exec Task에 robocopy를 사용하는 방법파일 다운로드1
12715정성태7/17/202123539오류 유형: 736. Windows - MySQL zip 파일 버전의 "mysqld --skip-grant-tables" 실행 시 비정상 종료 [1]
12714정성태7/16/202116753오류 유형: 735. VCRUNTIME140.dll, MSVCP140.dll, VCRUNTIME140.dll, VCRUNTIME140_1.dll이 없어 exe 실행이 안 되는 경우
12713정성태7/16/202118853.NET Framework: 1077. C# - 동기 방식이면서 비동기 규약을 따르게 만드는 Task.FromResult파일 다운로드1
12712정성태7/15/202117483개발 환경 구성: 579. Azure - 리눅스 호스팅의 Site Extension 제작 방법
12711정성태7/15/202116943개발 환경 구성: 578. Azure - Java Web App Service를 위한 Site Extension 제작 방법
12710정성태7/15/202120276개발 환경 구성: 577. MQTT - emqx.io 서비스 소개
12709정성태7/14/202115787Linux: 42. 실행 중인 docker 컨테이너에 대한 구동 시점의 docker run 명령어를 확인하는 방법
12708정성태7/14/202120206Linux: 41. 리눅스 환경에서 디스크 용량 부족 시 원인 분석 방법
12707정성태7/14/202186727오류 유형: 734. MySQL - Authentication method 'caching_sha2_password' not supported by any of the available plugins.
12706정성태7/14/202118116.NET Framework: 1076. C# - AsyncLocal 기능을 CallContext만으로 구현하는 방법 [2]파일 다운로드1
12705정성태7/13/202118928VS.NET IDE: 168. x64 DLL 프로젝트의 컨트롤이 Visual Studio의 Designer에서 보이지 않는 문제 - 두 번째 이야기
12704정성태7/12/202117439개발 환경 구성: 576. Azure VM의 서비스를 Azure Web App Service에서만 접근하도록 NSG 설정을 제한하는 방법
12703정성태7/11/202122417개발 환경 구성: 575. Azure VM에 (ICMP) ping을 허용하는 방법
12702정성태7/11/202118691오류 유형: 733. TaskScheduler에 등록된 wacs.exe의 Let's Encrypt 인증서 업데이트 문제
12701정성태7/9/202118278.NET Framework: 1075. C# - ThreadPool의 스레드는 반환 시 ThreadStatic과 AsyncLocal 값이 초기화 될까요?파일 다운로드1
12700정성태7/8/202118775.NET Framework: 1074. RuntimeType의 메모리 누수? [1]
12699정성태7/8/202117409VS.NET IDE: 167. Visual Studio 디버깅 중 GC Heap 상태를 보여주는 "Show Diagnostic Tools" 메뉴 사용법
... 46  47  48  49  [50]  51  52  53  54  55  56  57  58  59  60  ...