c# 文件编译的过程
两次编译的过程整个流程的核心思路是.NET 用两次编译把写代码和跑代码这两件事解耦开来。第一次编译源码 → IL开发时完成你写的 C# 代码.cs文件通过csc.exe编译器翻译成一种叫做IL中间语言Intermediate Language的中间产物最终打包成.exe或.dll文件。这一步在你的开发机上完成IL 不是机器码任何 CPU 都还不能直接执行它。VB.NET、F# 等语言也有自己的编译器但最终都会生成同一种 IL这就是 .NET 能做到跨语言互调的根本原因。第二次编译IL → 机器码运行时完成当用户在自己的机器上运行这个.exe时CLR公共语言运行时启动其中的JITJust-In-Time即时编译器读取 IL根据当前机器的 CPU 架构即时翻译成真正的机器码x86 / x64 / ARM 等然后交给操作系统执行。为什么要这样设计这个设计带来了两个核心好处一是跨平台同一份.dll文件可以在 Windows/Linux/macOS 上运行由各平台的 CLR 负责翻译成对应机器码二是跨语言C# 和 VB.NET 可以互相调用对方的库因为底层都是同一种 IL。托管代码 vs 非托管代码的区别以及 CLR 到底帮你管了哪些事。核心区别有没有人管你非托管代码如 C写的程序编译出来直接就是 CPU 机器指令操作系统拿到就跑。好处是快、直接坏处是所有事情都要程序员自己负责——内存要自己申请自己释放忘了就内存泄漏越界访问就直接崩溃没有任何保护。托管代码C# 就是这类写的程序产物是 IL 中间语言必须交给 CLR 来代为管理CLR 再翻译成机器码给操作系统执行。多了这一层CLR 就能替你做很多事CLR 替你管的六件事JIT 编译把 IL 实时翻译成当前机器的机器码上一篇讲的第二次编译就在这里发生内存管理你用new创建对象CLR 自动在堆上给你分配空间不用手动malloc垃圾清理GC你不再用的对象GC 会自动回收内存彻底告别内存泄漏异常处理程序出错时有统一的try/catch机制兜底不会直接崩给用户看类加载器程序集dll按需加载用到哪个加载哪个不用手动管理反射程序运行时可以动态查询这个类有哪些方法、属性WPF 的数据绑定底层就大量依赖反射对学 C# 的你意味着什么你写的每一行 C# 代码都是托管代码受 CLR 保护。这意味着你几乎不需要关心内存管理不会因为忘记释放内存而崩溃异常会被妥善捕获。代价是相比 C 有一点点性能开销但对于桌面应用WPF来说完全可以忽略不计。CLR CTS CLS三者是层层包含的关系从大到小CLR ⊃ CTS ⊃ CLS。CLR公共语言运行时是最大的那层是整个 .NET 的运行环境就像前两张图讲的虚拟机。它负责 JIT 编译、垃圾回收、异常处理等所有运行时工作。CTS 和 CLS 都是 CLR 的组成部分。CTS通用类型系统住在 CLR 里面它回答的问题是不同语言C#、VB.NET、F#之间类型怎么统一 CTS 规定了 .NET 平台上所有合法类型的定义规则比如什么是类、什么是结构体、什么是接口、值类型和引用类型怎么区分。有了 CTSC# 的int和 VB.NET 的Integer才能被认定为同一个底层类型System.Int32两种语言的代码才能互相传递数据。CLS公共语言规范是 CTS 的一个子集是更小的那一层。它回答的是如果我想写一个库让所有 .NET 语言都能调用我必须遵守哪些规则 CLS 是各语言之间的最小公约数。举个例子C# 支持无符号整数uint但 VB.NET 不支持所以uint不在 CLS 里。你写的公共库如果用了uint作为公开接口VB.NET 的用户就无法使用它。用一句话概括三者的分工CLR 负责跑程序CTS 负责统一类型CLS 负责跨语言互通。对你学 C# 和 WPF 而言实际编码时不需要刻意操作这三者但理解它们能帮你看懂很多为什么 .NET 这样设计的问题。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2510636.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!