문제

다음 일반 방법에 대해 생성 된 MSIL 코드를 살펴 보겠습니다.

public static U BoxValue<T, U>(T value)
  where T : struct, U
  where U : class
{
  return value;
}

바라보다:

.method public hidebysig static !!U  BoxValue<valuetype .ctor
 ([mscorlib]System.ValueType, !!U) T,class U>(!!T 'value') cil managed
{
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  box        !!T
  IL_0006:  unbox.any  !!U
  IL_000b:  ret
}

그러나 위의 일반 코드의 경우 더 효율적인 IL 표현은 다음과 같습니다.

  IL_0000:  ldarg.0
  IL_0001:  box        !!T
  IL_0006:  ret

값이 상자에 걸린 것으로 제약으로 알려져 있습니다. 참조 유형. Unbox.any Opcode는 이후로 완전히 중복됩니다 box OPCODE IL Stack의 값은 이미 유효한 참조입니다. !!U, Unboxing없이 사용할 수 있습니다.

C# 3.0 컴파일러가 제약 메타 데이터를 사용하여보다 효율적인 일반 코드를 방출하지 않는 이유는 무엇입니까? Unbox.any는 작은 오버 헤드를 제공하지만 (4x-5 배 단지 느리게),이 시나리오에서 더 나은 코드를 방출하지 않는 이유는 무엇입니까?

도움이 되었습니까?

해결책

검증 자의 일부 문제로 인해 컴파일러가이를 수행하는 것처럼 보입니다.

컴파일러를 생성하려는 IL은 검증 할 수 없으므로 C# 컴파일러는이를 생성 할 수 없습니다 ( "안전하지 않은"컨텍스트 외부의 모든 C# 코드는 검증 할 수 있어야 함).

"검증 유형 호환성"에 대한 규칙은 ECMA 사양의 1.8.1.2.3, Partion III 섹션에 나와 있습니다.

그들은 다음 규칙을 사용하여 유형 't'또는 (s : = t)와 호환되는 검증이라고 말합니다.

  1. : =는 반사적입니다] 모든 검증 유형 s, s : = s에 대해
  2. : =는 전이적입니다] 모든 검증 유형 s, t 및 u의 경우 s : = t 및 t : = u 인 경우 s : = u.
  3. s : = t s가 기본 클래스 인 경우 t 또는 t와 t로 구현 된 인터페이스는 값 유형이 아닙니다.
  4. 개체 : = t가 인터페이스 유형 인 경우 t.
  5. s : = t s와 t가 모두 인터페이스이고 t의 구현에는 s 구현이 필요합니다.
  6. s : = s가 객체 유형이거나 인터페이스 인 경우 null
  7. s [] : = t [] s : = t와 배열이 벡터 (0 기반, 순위 1)이거나 벡터가 아니며 둘 다 같은 순위를 갖는 경우. (이 규칙은 배열 공분산을 다룹니다.)
  8. s와 t가 메소드 포인터 인 경우, 서명 (반환 유형, 매개 변수 유형 및 호출 규칙)이 동일하다면 s : = t.

이 규칙 중이 경우에 적용 할 수있는 유일한 규칙은 #3입니다.

그러나 'u'는 't'의 기본 클래스가 아니기 때문에 #3은 코드에 적용되지 않으며 't'의 기본 인터페이스가 아니므로 '또는'점검은 false를 반환합니다.

이는 검증자를 전달하는 방식으로 박스형 T를 U로 변환하기 위해 일부 명령을 실행해야 함을 의미합니다.

원하는 코드를 생성하는 것이 실제로 검증 가능하도록 확인 규칙이 변경되어야한다는 데 동의합니다.

그러나 기술적으로 컴파일러는 ECMA 사양을 기반으로 "올바른"작업을 수행하고 있습니다.

Microsoft의 누군가에게 버그를 제출해야합니다.

다른 팁

이러한 제약은 이상하게 보입니다.

where T : struct, U
where U : class

t는 값 유형이지만 동시에 참조 유형 인 u에서 상속해야합니다. 어떤 유형이 위의 제약 조건을 충족시킬 수 있는지 궁금해 하고이 방법을 호출 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top