不用IDE写C#的Hello World的方法
作者:lijiao 发布时间:2022-01-25 19:24:58
用Visual Studio等IDE写C#的Hello World非常简单,但脱离了IDE你能不能打印出Hello World呢?这不是说工作时脱离IDE,而是学习一下CLR的执行模型.
Hello World
新建一个记事本,输入如下代码,另存为HelloWorld.txt.
using System;
namespaceHelloWorld
{
classProgram
{
static voidMain(string[] args) {
Console.WriteLine("Hello World!");
Console.ReadKey();
}
}
}
打开Visual Studio 2008(2005,2010) 命令提示程序
却换到HelloWorld.txt的目录
运行命令:csc /out:Hello.exe HelloWorld.txt
如无意外,将会编译出Hello.exe,能打印出Hello World.
CLR执行模型-编译期
CLR程序的执行过程大致分为两步,编译期和运行期,编译期过程大致如下图:
其中编译期逻辑上也可分为两步:
CLR(C#)编译器接受源代码文件,并编译为托管模块.托管模块包括IL代码,元数据,CLR头等组成部分.上面的例子中就是将HelloWorld.txt编译成托管模块.
一般程序集都会包含很多源代码文件(这里只有HelloWorld.txt)和资源文件,第二步就是把各个源代码文件和资源文件对应编译结果合并成程序集.
执行上面两步就可以得到一个XX.dll或XX.exe的程序集.就像上面的Hello.exe.
编译器如何知道要编译成托管模块还是资源文件?其实是必须明确告诉编译器每个文件的怎么编译,这个对应Visual Studio的文件属性的生成操作.
右击任何Visual Studio解决资源方案的文件-->属性-->生成操作:
指定Class1为嵌入的资源,用ILSpy查看会发现只是把Class1嵌入到程序集中,名称为:命名空间.文件名:
你甚至可以将一张图片设为编译让编译器试图去编译它,不过会报错.
运行期
上面生成了程序集,程序集内的是IL代码,它还不是可运行的代码.IL是与CPU无关的机器语言.直到程序集被调用,才会由JIT(Just-in-Time,实时)编译器编译为本机代码(CPU指令).在运行时,CLR执行如下步骤:
◆ 检查程序集的安全特性;
◆ 在内存中分配空间;
◆ 把程序集中的可执行代码发送给JIT编译器,把其中一部分编译成本机代码(CPU指令).
程序集的可执行代码在需要的时候由JIT编译编译,然后本机代码(CPU指令)就被缓存以备后来的程序中执行.一旦应用程序终止,编译好的本机代码也会被丢弃.
例如如果将上面的代码改为:
static void Main(string[] args) {
Console.WriteLine("Hello");
Console.WriteLine("World!");
Console.ReadKey();
}
第一个WriteLine需要先JIT编译,再执行.而由于已编译WriteLine的代码,所以第二个WriteLine会直接执行内存块中的代码,跳过JIT编译.
由于分配内存,JIT编译过程等,所以程序会在第一次运行时造成一些性能损失,写ASP.NET时这种感觉特变明显,按了F5会等很久才会显示首页.
下面模拟感受这个过程.用一大堆类延长内存分配的时间,参考这个文件HelloWorld.css(博客园不支持txt格式):
再次运行命令:csc /out:Hello.exe HelloWorld.txt,得到Hello.exe,执行时发现有一定的延迟才会打印出Hello World.
生成本机代码
使用.NET提供的NGen.exe,可以将IL代码编译成本机代码.可以解决上面的问题.NGen.exe有两个作用:
加快应用程序的启动速度.因为代码已编译为本机代码,运行时不需要再花时间编译
减少应用程序的程序集.如果一个程序集会同时加载多个进程.NGen.exe会将IL编译成本机代码,并保存到一个单独的文件中.这样就可以通过"内存映射"的方式,同时映射到多个进程中,使代码共享.避免每个进程一份代码.
再次运行Visual Studio 2008(2005,2010) 命令提示程序
运行如下命令:ngen install Hello.exe:
命令完成(在我的机器大概要10秒左右,到能再次输入命令才完成)后运行Hello.exe会发现马上就能打印出Hello World,没有任何延迟.
对于ASP.NET,Microsoft另外提供了aspnet_compiler.exe,我们可以在ASP.NET程序建一个脚本(.bat)预编译程序.以下是一个示例(from老赵的程序):
%SYSTEMROOT%\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler -v / -p .\MyMvcDemo.Web.UI -f -errorstack .\Compliled
PAUSE
关于aspnet_compiler.exe不多介绍,感兴趣的可以自己搜索相关资料.


猜你喜欢
- 前言今天刚买了一台服务器,上面什么都没有,正好可以出一期 Linux 上配置java环境的教程可以看到我这个服务器上面是没有配置过 java
- 通常在C#的实际开发过程中,会发现设置其属性ScriptErrorsSuppressed无法达到屏蔽脚本错误效果,但是可以通过下面两种方式实
- ThreadLocal与线程成员变量还有区别,ThreadLocal该类提供了线程局部变量。这个局部变量与一般的成员变量不一样,Thread
- 两种方法,第一种是静态开启方法把application 或者 activity的主题设置为Theme.Holo即可<?xml vers
- 有时候我们在使用java编程的时候,想启动线程,怎么启动呢,下面来分享一下方法第一步在我们的电脑上打开eclipse,创建一个java项目,
- 1:RabbitMQ是个啥?(专业术语参考自网络)RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间
- 目录1、在运行时,由java解释器自动引入,而不用import语句引入的包是()。2、以下关于集合类ArrayList、LinkedList
- 上次给一个网站写网站 前后端分离 最后跪在ajax跨域上面了 自己在网上找了个方法 亲试可用
- 本文实例讲述了WPF弹出自定义窗口的方法。分享给大家供大家参考,具体如下:测试环境:[1]VS2010SP1[2]WPF(.NET Fram
- 处理提交数据1、提交的域名称和处理方法的参数名一致提交数据 : http://localhost:8080/hello?name=xiaoh
- 一. 可变字符串1. 简介在Java中,我们除了可以通过String类创建和处理字符串之外,还可以使用StringBuffer和String
- C#延时函数sleepsleepusing System.Threading; //导入命名空间,类Thread就在此空间中Th
- 由于Android项目开源所致,市面上出现了N多安卓软件市场。为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们
- Redis是一个缓存消息中间件及具有丰富特性的键值存储系统。Spring Boot为Jedis客户端库和由Spring Data Redis
- 本文主要介绍了spring-boot-maven-plugin报红解决方案,亲测有效,具体如下:<?xml version="
- 一、Service简介Service是Android程序中四大基础组件之一,它和Activity一样都是Context的子类,只不过它没有U
- 本文实例讲述了C#通过链表实现队列的方法。分享给大家供大家参考。具体实现方法如下:public class Node{ public int
- Java Config 下的Spring Test方式用了三种方式:1.纯手动取bean:package com.wang.test;imp
- ProgressBar进度条,分为旋转进度条和水平进度条,进度条的样式根据需要自定义,之前一直不明白进度条如何在实际项目中使用,网上演示进度
- 一、项目简述功能: 主页显示商品; 所有二手书商品展示,可进行商品搜索; 点击商品进入商品详情页,具有立即购买和加入购物车功能,可增减购买商