让我们检查集产生的代码,用于以下通用的方法:

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 操作码是完全多余的,因为后 box 操作的价值在伊堆已经将是一个有效的参考 !!U, 可以使用没有任何拆箱.

为什么不C#3.0编译器不使用限制的元数据以发出更有效的通用代码?拆箱.任何使一个小的开销,(仅有4-5倍的速度较慢),但为什么不发更好的代码,在这种情况?

有帮助吗?

解决方案

它看起来像编译器,这是否因为一些问题与验证程序。

伊尔,你会喜欢的编译器产生的是不可核查的,因此C#编译器不能产生(C#外的代码"不安全"背景下应该可以核查).

规则"的核查类型兼容性"的部分中给出的1.8.1.2.3,部分三的通信机制详解的规范。

他们说,这一类型的"S"是验证兼容类型的'T'或(S:=T)使用下列规则:

  1. [:=是反思的]所有的核查类型,S:=S
  2. [:=是传递的]所有的核查类型S,T、U如果S:=T和T:=U,那么S:=U.
  3. S=T如果是基类的T或一个接口实现的T和T不是一个值的类型。
  4. 对象:=T如果T是一个接口的类型。
  5. S=T如果S和T两个接口,并实施T要求的执行情况 S
  6. S=null如果一个目的类型或一个接口
  7. S[]:=T[]如果S:=T和阵列是两个载体(基于零,职级一)或两者都不是 是一个矢量和两者具有相同的等级。(这条规则涉及列协方差。)
  8. 如果S和T方法的指针,那么S:=T如果签字(回归类型、参数和类型 呼吁《公约》)是相同的。

这些规则,只有一个可适用于这种情况下为#3.

然而,#3不适用于代码,因为'U'不是一个基类的'T',并且它不是一个基本界面的'T',所以'或'检查返回错误的。

这意味着一些指令需要进行执行了转换一个装箱T U的方式,将通过检验器。

我会同意你的看法,核查规定应该改变,因此,产生的代码你想要的是实际上可以核查的。

从技术上讲,但是,编译器是做"正确的"的事情基础的通信机制详解的规范。

你应该文件的一个错误的人。

其他提示

这些约束看起来很奇怪:

where T : struct, U
where U : class

T为值类型,但在相同的时间必须距离U是一个引用类型继承。我不知道什么类型能够满足上述限制,并允许我们调用此方法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top