在进行向上或向下投射时,幕后真的会发生什么?我有一个想法,当做某事时:
string myString = "abc";
object myObject = myString;
string myStringBack = (string)myObject;
Run Code Online (Sandbox Code Playgroud)
最后一行中的强制转换只有目的告诉编译器我们是安全的,我们没有做错任何事.所以,我认为实际上代码本身不会嵌入任何强制转换代码.看来我错了:
.maxstack 1
.locals init (
[0] string myString,
[1] object myObject,
[2] string myStringBack)
L_0000: nop
L_0001: ldstr "abc"
L_0006: stloc.0
L_0007: ldloc.0
L_0008: stloc.1
L_0009: ldloc.1
L_000a: castclass string
L_000f: stloc.2
L_0010: ret
Run Code Online (Sandbox Code Playgroud)
为什么CLR需要类似的东西castclass string?
向下转换有两种可能的实现方式:
castclass something.当你到达执行的代码行时castclass,CLR会尝试进行强制转换.但是,如果我省略了castclass字符串行并尝试运行代码,会发生什么?castclass.由于所有引用类型都具有类似的内部结构,如果您尝试在Form实例上使用字符串,它将抛出错误用法的异常(因为它检测到Form不是字符串或其任何子类型).另外,来自C#4.0的以下statamente在Nutshell中是否正确?
Upcasting and downcasting between compatible reference types performs reference
conversions: a new reference is created that points …Run Code Online (Sandbox Code Playgroud) 我正在看这个,它的起始评论说它存在,因为
throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
Run Code Online (Sandbox Code Playgroud)
生成的 IL 代码多于
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);
Run Code Online (Sandbox Code Playgroud)
我在代码中找不到它,但就像它的类似方法一样,我假设只是调用throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));或其他东西。
ThrowHelper 类是否真的有助于减少生成的 IL 代码,或者考虑到从 生成的 IL 代码,它是否相同(或更多)ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);?
编辑:文件开头的注释中显示的 IL 仅来自对该ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);方法内的实际代码的调用。还是我错了?
最近提到的PostSharp让我想起了这个:
去年我工作的地方,我们正在考虑使用PostSharp将检测注入我们的代码中.这是在Team Foundation Server团队构建/持续集成环境中.
考虑到这一点,我对PostSharp的运行方式产生了一种唠叨的感觉 - 它编辑了编译器生成的IL.这让我感到困扰.
我并不担心PostSharp不能正常工作; 我很担心这是我第一次回忆起这样的工具.我担心其他工具可能不会考虑到这一点.
事实上,随着我们前进,我们确实遇到了一些问题,因为PostSharp对原始IL所处的文件夹感到困惑.这打破了我们的构建.它似乎是由于与MSBUILD目标的冲突解决了项目引用.冲突似乎是由于PostSharp使用临时目录来存储IL的未修改版本.
无论如何,我当时没有StackOverflow来引用!既然我这样做了,我想问你们所有人是否知道编辑IL作为构建过程的一部分的任何其他工具; 或者Microsoft是否在Visual Studio,MSBUILD,Team Build等中考虑了这种工具.
更新:感谢您的回答.
最重要的是,至少在VS 2010中,微软真的应该意识到这种事情会发生.因此,如果在VS2010中存在这方面的问题,那么微软可能会分担责任.
在做一些阅读时,我遇到了"中间语言"和"3AC"这两个术语.
据我所知,IL是源代码编译过程中的中间"步骤".更具体地说,我正在阅读字节码(Java)和C.
我解释它的方式(纠正我,如果错了)是;
源代码1(例如Lisp) - >中间语言(C) - >汇编语言 - >机器码
源代码2(例如Java) - >字节码 - > Java虚拟机
基于此,我很难看到三地址代码(TAC/3AC)在哪里发挥作用,以及它的用途.
似乎当我使用OpenCover检测装配时,带有SecurityTransparent的装配属性(似乎是AllowPartiallyTrustedCallers的将抛出VerificationException。我想知道为什么会这样,以及是否有另一种解决方案来重新编译不包含那些属性的程序集,即条件编译,如在MVC3的下载代码中所看到的(但奇怪的是,当我浏览该程序时,找不到相同的代码)代码库上的存储库)。请注意,如果没有这些程序集属性,覆盖范围将正常运行。
OpenCover使用CALLI指令将检测数据(序列点标识符)发送到探查器。看来,调用该指令的行为会导致异常的发生。检测部分似乎很好,并且JIT可以毫无问题地编译新的检测方法。检测行为不会引起问题,因为如果我删除除使Tiny方法变为Fat和小分支之外的所有检测,则代码将长时间执行而不会出现问题。
当前,我正在使用Mono.Cecil来检查通过“覆盖范围内”过滤器的程序集,并在跳过检测过程然后继续操作时向用户报告问题,但是我想知道我是否可以进行分析时请避免此问题并避免重新编译。
因此,总结两个问题“为什么会发生?” 和“我可以不重新编译就避免它吗?”
注意:PartCover似乎也出现此问题,它使用另一种方法来记录访问点。
注意:我是OpenCover(一个开放源代码覆盖工具)的开发人员,并且是PartCover的维护者。
该LLVM语言参考指出,它可用于
作为磁盘上的bitcode表示(适合Just-In-Time编译器的快速加载)
这种表现有多稳定?例如,我现在可以使用LLVM 3.1生成它,并且仍然期望它可以使用未来的LLVM,比如三年假设的LLVM 4.5吗?
假设我没有外部依赖项,我可以使用它为不同的架构生成二进制文件吗?
CIL是一种面向对象的汇编语言,完全基于堆栈.它的字节码被翻译成本机代码,或者 - 最常见的 - 由虚拟机执行.
为什么我们需要CIL?是不是可以将C#转换为本机代码而不是CIL?如果所有.Net语言都编译成CIL,为什么不使用C#而不是IL?CIL比C#或VB更具表现力吗?
我试图在运行时将以下代码作为 IL 代码发出。
class TestObject {
public int Hello {get;set;}
public int Test {get;set;}
}
static TestObject test(BinaryReader reader) {
var a = new TestObject();
a.Hello = reader.ReadInt32();
a.Test = reader.ReadInt32();
return a;
}
Run Code Online (Sandbox Code Playgroud)
LINQPad 显示:
test:
IL_0000: nop
IL_0001: newobj UserQuery+TestObject..ctor
IL_0006: stloc.0 // a
IL_0007: ldloc.0 // a
IL_0008: ldarg.0
IL_0009: callvirt System.IO.BinaryReader.ReadInt32
IL_000E: callvirt UserQuery+TestObject.set_Hello
IL_0013: nop
IL_0014: ldloc.0 // a
IL_0015: ldarg.0
IL_0016: callvirt System.IO.BinaryReader.ReadInt32
IL_001B: callvirt UserQuery+TestObject.set_Test
IL_0020: nop
IL_0021: ldloc.0 // a
IL_0022: stloc.1 …Run Code Online (Sandbox Code Playgroud) 我想创建一个从 SQL 到 XQuery 的转换器。
我想解析 SQL 并生成一个中间结构,然后使用它来生成 XQuery 查询。
(注意 - 我想使用中间表示,因为我期待将来将 SQL 翻译成其他查询语言)
但我不知道一旦定义了语法,如何生成翻译器。我想使用 ANTLR 并且确实已经创建了语法。我目前被语法文件困住并继续构建翻译器,因为我不知道制作翻译器的下一步是什么。
考虑作业,a := b*-c + b*-c.
图 1 上述语句的四元组
以下是红龙书的摘录。
如果多次使用相同的临时值,则间接三元组与四元组相比可以节省一些空间。原因是语句数组中的两个或多个条目可以指向结构的同一行
op-arg1-arg2。例如,下图中的行(14)和(16)可以组合,然后我们可以组合(15)和(17)。图2 三地址语句的间接三重表示
我的问题是摘录中关于使用间接三元组节省空间的内容,我们也可以对四元组说同样的话,如下:
我们可以将语句的三地址代码写为右侧的代码,而不是上图中左侧的代码...然后我们将得到下面的四元组:
这正是摘录中关于间接三元组相对于四元组的优势的内容。
那么我们可以得出什么结论呢?