코드를 컴파일 할 때 생성되는 템플릿과는 달리 JIT가 제네릭을 컴파일한다는 것을 알고 있습니다.
리플렉션을 사용하여 런타임에 새로운 제네릭 형식을 만들 수 있습니다.
물론 제네릭의 제약 조건에 영향을 미칠 수 있습니다. 어느 의미 구문 분석기를 이미 통과했습니다.제네릭은 JIT 컴파일러에 의해 어떻게 컴파일됩니까?
누군가 처리 방법을 설명 할 수 있습니까? 그리고 정확히 어떻게됩니까?
(코드 생성 및 의미 검사 모두)
코드를 컴파일 할 때 생성되는 템플릿과는 달리 JIT가 제네릭을 컴파일한다는 것을 알고 있습니다.
리플렉션을 사용하여 런타임에 새로운 제네릭 형식을 만들 수 있습니다.
물론 제네릭의 제약 조건에 영향을 미칠 수 있습니다. 어느 의미 구문 분석기를 이미 통과했습니다.제네릭은 JIT 컴파일러에 의해 어떻게 컴파일됩니까?
누군가 처리 방법을 설명 할 수 있습니까? 그리고 정확히 어떻게됩니까?
(코드 생성 및 의미 검사 모두)
나는 Generics in C#, Java, and C++: A Conversation with Anders Hejlsberg을 읽는 것이 좋습니다.
Qn 1. JIT 컴파일러는 어떻게 generics를 컴파일합니까?
는 목록, 또는 다른 제네릭 형식을 컴파일 할 때 [...]를 CLR [공용 언어 런타임, 에서 , 그것은 아래로 컴파일 모든 일반 유형과 마찬가지로 IL [중간 언어] 및 메타 데이터 IL 및 메타 데이터에는 물론 매개 변수가 있다는 것을 알고있는 추가 정보가 포함되어 있지만 원칙에 따르면 일반 유형은 을 으로 컴파일하는 방식으로 컴파일합니다. 런타임에 응용 프로그램이 List에 첫 번째 참조 을 작성하면 시스템에서앤더스 헤 즐스 버그 : 인터뷰에서
List<int>
을 이미 요청한 경우 이 표시됩니다. 그렇지 않은 경우List<T>
및 유형 인수 int의 IL 및 메타 데이터를 피드합니다. JITer 인 IL을 JIT 처리하는 과정에있는 도 을 사용하여 type 매개 변수를 대체합니다.는 [...]
지금, 우리가 그 다음 일은 값이 유형-등
List<int>, List<long>, List<double>, List<float>
로 - 우리가 실행 기본 코드의 고유의 복사본을 만들 수있는 모든 유형 인스턴스화입니다. 따라서List<int>
은 자체 코드를 얻습니다.List<long>
은 자체 코드를 가져옵니다.List<float>
은 자체 코드를 가져옵니다. 모든 참조 유형에 대해 우리는 코드를 공유합니다. 왜냐하면 대표적으로 이 동일하기 때문입니다. 그것은 단지 포인터 일뿐입니다.
QN 2 일
새로운 제네릭 형식 이 반사를 사용하여 런타임에서 생성 될 수 있다는 것이다. 물론 generic의 제약 조건 인 에 영향을 미칠 수 있습니다. 어느 이미 의미 파서를 통과 시켰습니다. 누군가가 을 어떻게 처리 할 수 있습니까?
기본적으로 IL는 '정적으로 구성된'유형을 위해 할 수있는 단지 C# 컴파일러와 같은 런타임에 제네릭 형식 '을 동적으로 생성'의 CLR이 제약 조건을 확인할 수 있습니다 일반적인 유형의 높은 수준의보기를 유지 컴파일 타임에 C# 소스 코드.
앤더스 헤 즐스 버그 : 여기
다른 조각 (강조 광산)의 [...] 제약으로, 당신은 동적 코드의 체크 아웃 및 그것에서 검증 을 할 수 있다고 호이스트 수 있습니다 컴파일 시간은 이거나로드 시간. K가 에 IComparable을 구현해야한다고 말하면 몇 가지 일이 발생합니다. K 유형의 모든 값이 인 경우 의미가있는 인터페이스에 인터페이스가 구현되어 있기 때문에 캐스트없이 인터페이스 메소드에 직접 액세스 할 수 있습니다. 당신이 시도하고 는 해당 유형의 인스턴스를 만들 때마다, 컴파일러는 당신이 K 인수로 제공 모든 유형이 에서 IComparable을 구현하는 것을 확인합니다, 그렇지 않으면 당신은 컴파일 시간 오류가 발생합니다. 리플렉션으로 작업하는 경우 예외가 발생합니다.브루스 Eckel : 당신은 컴파일러와 런타임을 말했다.
앤더스 헤 즐스 버그 : 컴파일러 검사 을, 그러나 당신은 또한 반사 런타임시에 그 일을 할 수 있고, 다음 시스템을 확인합니다. 앞서 말했듯이 컴파일시에 수행 할 수있는 모든 것, 도 런타임에 리플렉션으로 수행 할 수 있습니다.
참조 유형 제네릭은 모두 과 동일합니다. 유형입니다. 값 유형 제네릭은 을 개별적으로 인스턴스화합니다.
참조 유형은 모두 실제로 Object
참조 (4 또는 8 바이트)이지만 값 유형은 다르고 스택 레이아웃 차이 등으로 인해 단일 코드 조각으로 처리 할 수 없기 때문에 이러한 결과가 발생합니다. 따라서 다중 값 유형이있는 일반 유형의 사본은 메모리 사용량을 많이 증가 시키지만 참조 유형을 사용하여 여러 사본을 인스턴스화하는 것은 그렇지 않습니다.
그들은 같은 유형이 아닙니다. 그것들은 멤버 함수 (메쏘드)를위한 동일한 기계 코드를 공유하지만 ... 각각은 정적 멤버 변수의 복사본을 가진 구별 된 타입이다. –
@BenVoigt : 맞아 ... 설명해 주셔서 고마워요. – Mehrdad
제약 조건은 컴파일러에서 강제로 적용되는 것이 아니라 지터가 검사합니다. 제네릭에는별로 중요하지 않은 부분이 몇 가지 있는데, 어떻게 ngen-ed를 얻는 지 특히 흥분됩니다. 그것들은 5 년이 걸렸습니다. –