用vb.net能写出不受托管的程序吗?

ganenpingsohucom 2003-05-27 11:44:20
能用vb.net写一个可执行的程序,不需要.netframework支持的,行吗?
用c#行不行啊?如果行,该怎样做啊?
...全文
31 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
untitled12 2003-05-27
  • 打赏
  • 举报
回复
什么叫受托管的程序
hzg_yujia 2003-05-27
  • 打赏
  • 举报
回复
不需要.netframework支持肯定不行。
但是非托管代码可以写出来的
第4章 ASP.NET的网页代码模型及生命周期 从本章开始,就进入了ASP.NET应用程序开发的世界。在了解了C#的结构,以及面向对象的概念后,就可以从面向对象的思想开发ASP.NET应用程序。在ASP.NET中,能够使用面向对象的思想和软件开发中的一些思想,例如封装、派生、继承以及高级的设计模式等。本章首先介绍ASP.NET中最重要的概念---网页代码模型。 4.1 ASP.NET的网页代码模型 在ASP.NET应用程序开发中,微软提供了大量的控件,这些控件能够方便用户的开发以及维护。这些控件具有很强的扩展能力,在开发过程中无需自己手动编写。不仅如此,用户还能够创建自定义控件进行应用程序开发以扩展现有的服务器控件的功能。 4.1.1 创建ASP.NET网站 在ASP.NET中,可以创建ASP.NET网站和ASP.NET应用程序,ASP.NET网站的网页元素包含可视元素和页面逻辑元素,并不包含designer.cs文件。而ASP.NET应用程序包含designer.cs文件。创建ASP.NET网站,首先需要创建网站,单击【文件】按钮,在下拉菜单中选择【新建网站】选项,单击后会弹出对话框用于ASP.NET网站的创建,如图4-1所示。 图4-1 新建ASP.NET网站 在【位置】选项中,旁边的【下拉菜单】可以按照开发的需求来写,一般选择文件系统,地址为本机的本地地址。语言为.NET网站中使用的语言,如果选择Visual C#,则默认的开发语言为C#,否则为Visual Basic。创建了ASP.NET网站后,系统会自动创建一个代码隐藏页模型页面Default.aspx。ASP.NET网页一般由三部分组成,这三个部分如下所示。 q 可视元素:包括HTML,标记,服务器空间。 q 页面逻辑元素:包括事件处理程序和代码。 q designer.cs页文件:用来为页面的控件做初始化工作,一般只有ASP.NET应用程序(Web Application)才有。 ASP.NET页面中包含两种代码模型,一种是单文件页模型,另一种是代码隐藏页模型。这两个模型的功能完全一样,都支持控件的拖拽,以及智能的代码生成。 4.1.2 单文件页模型 单文件页模型中的所有代码,包括控件代码、事物处理代码以及HTML代码全都包含在.aspx文件中。编程代码在script标签,并使用runat=“server”属性标记。创建一个单文件页模型,在【文件】按钮中选择【新建文件】选项,在弹出对话框中选择【Web窗体】或在右击当前项目,在下拉菜单中选择【添加新建项】选项即可创建一个.aspx页面,如图4-2所示。 图4-2 创建单文件页模型 在创建时,去掉【将代码放在单独的文件中】复选框的选择即可创建单文件页模型的ASP.NET文件。创建后文件会自动创建相应的HTML代码以便页面的初始化,示例代码如下所示。 <%@ Page Language=“C#” %> <script runat=“server”> 无标题页
编译并运行,即可看到一个空白的页面被运行了。ASP.NET单文件页模型在创建并生成时,开发人员编写的类将编译成程序集,并将该程序集加载到应用程序域,并对该页的类进行实例化后输出到浏览器。可以说,.aspx页面的代码也即将会生成一个类,并包含内部逻辑。在浏览器浏览该页面时,.aspx页面的类实例化并输出到浏览器,反馈给浏览者。ASP.NET单文件页模型运行示例图如图4-3所示。 图4-3 单文件页模型 4.1.3 代码隐藏页模型 代码隐藏页模型与单文件页模型不同的是,代码隐藏页模型将事物处理代码都存放在cs文件中,当ASP.NET网页运行的时候,ASP.NET类生成时会先处理cs文件中的代码,再处理.aspx页面中的代码。这种过程被成为代码分离。 代码分离有一种好处,就是在.aspx页面中,开发人员可以将页面直接作为样式来设计,即美工人员也可以设计.aspx页面,而.cs文件由程序员来完成事务处理。同时,将ASP.NET中的页面样式代码和逻辑处理代码分离能够让维护变得简单,同时代码看上去也非常的优雅。在.aspx页面中,代码隐藏页模型的.aspx页面代码基本上和单文件页模型的代码相同,不同的是在script标记中的单文件页模型的代码默认被放在了同名的.cs文件中,.aspx文件示例代码如下所示。 <%@ Page Language=“C#” AutoEventWireup=“true” CodeFile=“Default.aspx.cs” Inherits=“_Default” %> 无标题页
从上述代码中可以看出,在头部声明的时候,单文件页模型只包含Language=“C#”,而代码隐藏页模型包含了CodeFile=“Default.aspx.cs”,说明被分离出去处理事物的代码被定义在Default.aspx.cs中,示例代码如下所示。 using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; //使用HtmlControls using System.Web.UI.WebControls; //使用WebControls using System.Web.UI.WebControls.WebParts; //使用WebParts public partial class _Default : System.Web.UI.Page //继承自System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } } 上述代码为Default.apx.cs页面代码。从上述代码可以看出,其格式与类库、编写类的格式相同,这也说明了.aspx页面允许使用面向对象的特性,如多态、继承等。但是ASP.NET代码隐藏页模型的运行过程比单文件页模型要复杂,运行示例图如图4-4所示。 图4-4 代码隐藏页模型 上述描述了代码隐藏类模型的页面生成模型。当页面被呈现之前,ASP.NET应用程序会解释并编译相应的cs文件中的代码,与此同时,ASP.NET应用程序还会将.aspx页面进行编译并生成.aspx页面对应的类。生成.aspx页面对应的类后会将该类与cs文件中的类进行协调生成新的类,该类会通过IIS在用户浏览页面时呈现在用户的浏览器中。 4.1.4 创建ASP.NET Web Application ASP.NET网站有一种好处,就是在编译后,编译器将整个网站编译成一个DLL(动态链接库),在更新的时候,只需要更新编译后的DLL(动态链接库)文件即可。但是ASP.NET网站却有一个缺点,编译速度慢,并且类的检查不彻底。 相比之下,ASP.NET Web Application不仅加快了速度,只生成一个程序集,而且可以拆分成多个项目进行管理。创建Application,首先需要新建项目用于开发Web Application,单击菜单栏上的【文件】按钮,在下拉菜单中选择【新建项目】选项,在弹出窗口中选择【ASP.NET应用程序】选项,如图4-5所示。 图4-5 创建ASP.NET应用程序 在创建了ASP.NET应用程序后,系统同样会默认创建一个Default.aspx页面,不同的是,多出了一个Default.aspx.designer.cs,用来初始化页面控件,一般不需要修改。 4.1.5 ASP.NET网站和ASP.NET应用程序的区别 在ASP.NET中,可以创建ASP.NET网站和ASP.NET应用程序,但是ASP.NET网站和ASP.NET应用程序开发过程和编译过程是有区别的。ASP.NET应用程序主要有以下特点: q 可以将ASP.NET应用程序拆分成多个项目以方便开发,管理和维护。 q 可以从项目中和源代码管理中排除一个文件或项目。 q 支持VSTS的Team Build方便每日构建。 q 可以对编译前后的名称,程序集等进行自定义。 q 对App_GlobalResources 的Resource强类支持。 ASP.NET WebSite编程模型具有以下特点: q 动态编译该页面,而不用编译整个站点。 q 当一部分页面出现错误不会影响到其他的页面或功能。 q 不需要项目文件,可以把一个目录当作一个Web应用来处理。 总体来说,ASP.NET网站适用于较小的网站开发,因为其动态编译的特点,无需整站编译。而ASP.NET应用程序适应大型的网站开发、维护等。 4.2 代码隐藏页模型的解释过程 在ASP.NET的代码隐藏页模型中,一个完整的.aspx页面包含两个页面,分别是以.aspx和.cs文件为后缀的文件,这两个文件在形成了整个Web窗体。在编译的过程中都被编译成由项目生成的动态链接库(.DLL),同时,.aspx页面同样也会编译。但是与.cs页面编译过程不同的是,当浏览者第一次浏览到.aspx页面时,ASP.NET自动生成该页的.NET类文件,并将其编译成另一个.DLL文件。 当浏览者再一次浏览该页面的时候,生成的.DLL就会在服务器上运行,并响应用户在该页面上的请求或响应,ASP.NET应用程序的解释过程图如4-6所示。 图4-6 代码隐藏页模型页面的执行过程 在客户端浏览器访问该页面时,浏览器会给IIS发送请求消息,IIS则会开始执行ASP.NET编译过程,如果不存在编译过后的DLL文件,则加载编译的类并创建对象。当创建对象完成,生成创建对象后的代码并生成一个ASPX页面代码,该页面代码反馈给IIS,IIS再反馈成HTML页面的形式给客户端。 4.3 代码隐藏页模型的事件驱动处理 在传统的ASP开发中,ASP的事件都是按照网页的顺序来处理的,一般情况下,ASP页面的事件都是从上到下处理事件,可以说ASP的开发是一个线性的处理模型。在用户的浏览操作中,每一次用户的操作都会导致页面重新被发送到服务器。因此,重复的操作必然导致客户端和服务器的往返过程,服务器必须重新创建页面,当创建页面后,服务器再按照原来的从上到下的顺序进行事件处理。 在ASP.NET中,通过使用模拟事件驱动模型的行为代替了ASP的线性处理模型。ASP.NET页框架模型隐式的为用户建立了事件和事件处理程序的关联。ASP.NET让用户可以为从浏览器传递的事件在服务器代码中设置相应的处理程序。假设某个用户正在浏览网站并与页面之间产生了某种交互,用户的操作就会引发事件,事件通过HTTP被传输到服务器。在服务器中,ASP.NET框架解释信息,并触发事件与之对应的处理程序。该程序可以是.aspx页面中的处理程序,也可以是开发者自定义的类库,或者COM组件等。事件驱动处理如图4-7所示。 图4-7 页面框架的事件驱动处理模型 上图则说明了当一个浏览者通过浏览器触发ASPX页面时,浏览器、服务器和服务器返回页的过程。 4.4 ASP.NET客户端状态 Web开发不像软件开发,Web应用实际上是没有状态的,这就说明Web应用程序不自动指示序列中的请求是否来自相同的浏览器或客户端,也无法判断浏览器是否一直在浏览一个页面或者一个站点,也无法判断用户执行了哪个操作并统计用户的喜好。 4.4.1 视图状态 从上面的章节中可以知道,当服务器每次的往返过程,都将销毁页面并重新创建新的页面。如果一个页面中的信息超出了页面的生命周期,那么这个页面中的相关信息就不存在了。如果注销了页面的信息,那么用户的一些信息可能就不存在了。 在ASP.NET中,网页包含视图状态来保存用户的信息,视图状态在页面发回到自身时,跨页过程存储和用户自己的页面的特定值,视图状态的优点如下所示。 q 不需要任何服务器资源。 q 在默认情况下,对控件启用状态的数据进行维护,不会被破坏。 q 视图状态的值经过哈希运算和压缩保护,安全性更高。 视图状态同样有一些缺点,缺点如下所示。 q 视图状态会影响性能,如果页面存储较大较多的值,则性能会有较大的影响。 q 在手机,移动终端上,可能无法保存视图状态中使用的值。 q 视图状态虽然安全性较高,但是还是有风险,如果直接查看页面代码,可以看到相应代码。 4.4.2 控件状态 ASP.NET中还提供了控件状态属性作为在服务器往返过程中存储自定义控件中的数据的方法。在页面控件中,如果有多个自定义控件使用多个不同的控件来显示不同的数据结构,为了让这些页面控件能够在在页面上协调的工作,则需要使用控件状态来保护控件,同时,控件状态是不能被关闭的。同样,控件状态也有它的优点,优点如下所示。 q 与视图状态相同的是,不需要任何服务器资源。 q 控件状态是不能被关闭的,提供了控件管理的更加可靠的方法。 q 控件状态具有通用性。 4.4.3 隐藏域 在ASP中,通常使用隐藏域保存页面的信息。在ASP.NET中,同样具有隐藏域来保存页面的信息,作为维护页面状态的一种形式,但是隐藏域的安全性并不高,最好不要在隐藏域保存过多的信息。隐藏域具有以下优点。 q 不需要任何服务器资源。 q 支持广泛,任何客户端都支持隐藏域。 q 实现简单,隐藏域属于HTML控件,无需像服务器控件那样有需要编程知识。 而隐藏域具有一些不足,如下所示。 q 具有较高的安全隐患。 q 存储结构简单。 q 同样,如果存储了较多的较大的值,则会导致性能问题。 q 如果隐藏域过多,则在某些客户端中被禁止。 q 隐藏域将数据存储在服务器上,而不存储在客户端。 注意:如果开发中,页面的隐藏域过多,这些隐藏域被存储在服务器。当客户端浏览页面的时候,会有一些防火墙扫描页面,以保证操作系统的安全,如果页面的隐藏域过多,那么这些防火墙可能会禁止页面的某些功能。 4.4.4 Cookie Cookie在客户端用户保存网站的少量的用户信息,服务器可以通过编程的方法获取用户信息,Cookie信息和页面请求通常一起发送到服务器,服务器对客户端传递过来的Cookie信息做处理。通常Cookie保存用户的登录状态、用户名等基本信息等等,在后面的章节会详细介绍使用ASP.NET操作Cookies。 4.4.5 客户端状态维护 虽然使用某些客户端状态并不使用服务器资源,但是这些状态都具有潜在的安全隐患,如Cookie。非法用户可以使用Cookie欺骗来攻击网站进行用户信息的获取,不过使用客户端状态能够使用客户端的资源从而提高服务器性能。使用客户端状态,虽然有安全隐患,但是具有良好的编程能力,以及基本的安全知识,能够较好的解决安全问题,同时也能够提高服务器性能。下面小结了一些客户端状态的优缺点。 q 视图状态:推荐当存储少量挥发到自身的页面的信息时使用。 q 控件状态:不需要任何服务器资源,控件状态是不能被关闭的,提供了控件管理的更加可靠和更通用的方法。 q 隐藏域:实现简单,但是在应用程序中会造成一些安全隐患。 q Cookie:实现简单,同样也能够简单的获取用户的信息,但是Cookie有大小的限制,不适宜存储大量的代码。 4.5 ASP.NET页面生命周期 ASP.NET页面运行时,也同类的对象一样,有自己的生命周期。ASP.NET页面运行时,ASP.NET页面将经历一个生命周期,在生命周期内,该页面将执行一系列的步骤,包括控件的初始化,控件的实例化,还原状态和维护状态等,以及通过IIS反馈给用户呈现成HTML。 ASP.NET页面生命周期是ASP.NET中非常重要的概念,了解ASP.NET页面的生命周期,就能够在合适的生命周期内编写代码,执行事务。同样,熟练掌握ASP.NET页面的生命周期,可以开发高效的自定义控件。ASP.NET生命周期通常情况下需要经历几个阶段,这几个阶段如下所示。 q 页请求:页请求发生在页生命周期开始之前。当用户请求一个页面,ASP.NET将确定是否需要分析或者编译该页面,或者是否可以在不运行页的情况下直接请求缓存响应客户端。 q 开始:发生了请求后,页面就进入了开始阶段。在该阶段,页面将确定请求是发回请求还是新的客户端请求,并设置IsPostBack属性。 q 初始化:在页面开始后,进入了初始化阶段。初始化期间,页面可以使用服务器控件,并为每个服务器控件进行初始化。 q 加载:页面加载控件。 q 验证:调用所有的验证程序控件的Vailidate方法,来设置各个验证程序控件和页的属性。 q 回发事件:如果是回发请求,则调用所有事件处理的程序。 q 呈现:在呈现期间,视图状态被保存并呈现到页。 q 卸载:完全呈现页面后,将页面发送到客户端并准备丢弃时,将调用卸载。 4.6 ASP.NET生命周期中的事件 在页面周期的每个阶段,页面将引发可运行用户代码进行处理事件。对于控件产生的事件,通过声明的方式执行代码,并将事件处理程序绑定到事件。不仅如此,事件还支持自动事件连接,最常用的就是Page_Load事件了,除了Page_Load事件以外,还有Page_Init等其他事件,本节将会介绍此类事件。 4.6.1 页面加载事件(Page_PreInit) 每当页面被发送到服务器时,页面就会重新被加载,启动Page_PreInit事件,执行Page_PreInit事件代码块。当需要对页面中的控件进行初始化时,则需要使用此类事件,示例代码如下所示。 protected void Page_PreInit(object sender, EventArgs e) //Page_PreInit事件 { Label1.Text = “OK”; //标签赋值 } 在上述代码中,当触发了Page_PreInit事件时,就会执行该事件的代码,上述代码将Lable1的初始文本值设置为“OK”。Page_PreInit事件能够让用户在页面处理中,能够让服务器加载时只执行一次而当网页被返回给客户端时不被执行。在Page_PreInit中可以使用IsPostBack来实现,当网页第一次加载时IsPostBack属性为false,当页面再次被加载时,IsPostBack属性将会被设置为true。IsPostBack属性的使用能够影响到应用程序的性能。 4.6.2 页面加载事件(Page_Init) Page_Init事件与Page_PreInit事件基本相同,区别在于Page_Init并不能保证完全加载各个控件。虽然在Page_Init事件中,依旧可以访问页面中的各个空间,但是当页面回送时,Page_Init依然执行所有的代码并且不能通过IsPostBack来执行某些代码,示例代码如下所示。 protected void Page_Init(object sender, EventArgs e) //Page_Init事件 { if (!IsPostBack) //判断是否第一次加载 { Label1.Text = “OK”; //将成功信息赋值给标签 } else { Label1.Text = “IsPostBack”; //将回传的值赋值给标签 } } 4.6.3 页面载入事件(Page_Load) 大多数初学者会认为Page_Load事件是当页面第一次访问触发的事件,其实不然,在ASP.NET页生命周期内,Page_Load远远不是第一次触发的事件,通常情况下,ASP.NET事件顺序如下所示。 q 1. Page_Init()。 q 2. Load ViewState。 q 3. Load Postback data。 q 4. Page_Load()。 q 5. Handle control events。 q 6. Page_PreRender()。 q 7. Page_Render()。 q 8. Unload event。 q 9. Dispose method called。 Page_Load事件是在网页加载的时候一定会被执行的事件。在Page_Load事件中,一般都需要使用IsPostBack来判断用户是否进行了操作,因为IsPostBack指示该页是否正为响应客户端回发而加载,或者它是否正被首次加载和访问,示例代码如下所示。 protected void Page_Load(object sender, EventArgs e) //Page_Load事件 { if (!IsPostBack) { Label1.Text = “OK”; //第一次执行的代码块 } else { Label1.Text = “IsPostBack”; //如果用户提交表单等 } } 上述代码使用了Page_Load事件,在页面被创建时,系统会自动在代码隐藏页模型的页面中增加此方法。当用户执行了操作,页面响应了客户端回发,则IsPostBack为true,于是执行else中的操作。 4.6.4 页面卸载事件(Page_Unload) 在页面被执行完毕后,可以通过Page_Unload事件用来执行页面卸载时的清除工作,当页面被卸载时,执行此事件。以下情况会触发Page_Unload事件。 q 页面被关闭。 q 数据库连接被关闭。 q 对象被关闭。 q 完成日志记录或者其他的程序请求。 4.6.5 页面指令 页面指令用来通知编译器在编译页面时做出的特殊处理。当编译器处理ASP.NET应用程序时,可以通过这些特殊指令要求编译器做特殊处理,例如缓存、使用命名空间等。当需要执行页面指令时,通常的做法是将页面指令包括在文件的头部,示例代码如下所示。 <%@ Page Language=“C#” AutoEventWireup=“true” CodeBehind=“Default.aspx.cs” Inherits=“MyWeb._Default” %> 上述代码中,就使用了@Page页面指令来定义ASP.NET页面分析器和编译器使用的特定页的属性。当代码隐藏页模型的页面被创建时,系统会自动增加@Page页面指令。 ASP.NET页面支持多个页面指令,常用的页面指令如下所示。 q @ Page:定义ASP.NET页分析器和编译器使用的页特定(.aspx文件)属性,可以编写为<%@ Page attribute=“value” [attribute=“value”…]%>。 q @ Control:定义ASP.NET页分析器和编译器使用的用户控件(.ascx文件)特定的属性。该指令只能为用户控件配置。可以编写为<%@ Control attribute=“value” [attribute=“value”…]%>。 q @ Import:将命名空间显示导入到页中,使所导入的命名空间的所有类和接口可用户该页。导入的命名空间可以是.NET Framework类库或用户定义的命名空间的一部分。可以编写为<%@ Import namespace=“value” %>。 q @ Implements:提示当前页或用户控件实现制定的.NET Framework接口。可以编写为<%@ Implements interface=“ValidInterfaceName” %>。 q @ Reference:以声明的方式指示,应该根据在其中声明此指令的页对另一个用户控件或页源文件进行动态编译和链接。可以编写为<%@ Reference page | control=“pathtofile” %>。 q @ Output Cache:以声明的方式空间ASP.NET页或页中包含的用户控件的输出缓存策略。可以编写为<%@ Output Cache Duration=“#ofseconds” Location=“Any | Client | Downstream | Server | None” Shared=“True |False” VaryByControl=“controlname” VaryByCustom=“browser | customstring” VaryByHeader=“headers” VaryByParam=“parametername” %> q @ Assembly:在编译过程中将程序集链接到当前页,以使程序集的所有类和接口都可用在该页上。可以编写为<%@ Assembly Name=“assemblyname” %>或<%@ Assembly Src=“pathname” %>的方式。 q @ Register:将别名与命名空间以及类名关联起来,以便在自定义服务器控件语法中使用简明的表示法。可以编写为<%@ Register tagprefix=“ tagprefix” Namespace=“namepace” Assembly=“assembly” %>或<%@ Register tagprefix=“ tagprefix” Tagname=“tagname” Src=“pathname” %>的方式。 4.7 ASP.NET网站文件类型 在ASP.NET中包含诸多的文件类型,这些类型的文件由ASP.NET支持和管理,而除了这些文件以外,其他的文件都由IIS托管。使用VS2008能够创建大部分可以使用ASP.NET托管运行的程序。同时,使用应用程序映射可以将文件类型映射到应用程序。当需要伪静态时,很可能需要将.html后缀托管到IIS中的应用扩展,因为默认情况下ASP.NET不会处理HTML的操作。 技巧:现在的网站构架中,生成静态是一种降低网站压力的一种很好的解决方案。在某些情况下,服务器可能需要伪静态支持,就是将.aspx页面后缀显式成.html后缀,让搜索引擎能够更好的搜录。 1.ASP.NET管理的文件类型 ASP.NET管理的文件类型能够在ASP.NET应用程序中被ASP.NET应用程序的不同模块进行访问和调用,这些文件可能是用户能够直接访问的,也有可能是用户无法直接访问的。ASP.NET管理的文件类型如表4-1所示。 表4-1 ASP.NET管理的文件类型 文件类型 保存位置 描述 .asax 根目录。 Global.asax 文件。包含 HttpApplication 对象的派生代码,用于重新展示 Application 对象。 .ascx 根目录或子目录。 可重用的自定义 Web 控件。 .ashx 根目录或子目录。 处理器文件。包含实现 IHttpHandler 接口的代码,用于处理输入请求。 .asmx 根目录或子目录。 XML Web Services 文件。包含由 SOAP 提供给其他 Web 应用的类对象和功能。 .aspx 根目录或子目录。 ASP.NET Web 窗体。包含 Web 控件和其他业务逻辑。 .axd 根目录。 跟踪视图文件。通常是 Trace.axd。 .browser App_Browsers 目录。 浏览器定义文件。用于识别客户端浏览器的可用特征。 .cd 根目录或子目录。 类图文件。 .compile Bin 目录。 定位于适当汇编集中的预编译文件。可执行文件(.aspx,.ascx,.master,theme)预编译后放在 Bin 目录。 .config 根目录或子目录。 Web.config 配置文件。包含用于配置 ASP.NET 若干特征的 XML 元素集。 .cs,.jsl,vb App_Code 目录。有些是 ASP.NET 的代码分离文件,位于与 Web 页面相同的目录。 运行时被编译的类对象源代码。类对象可以是 HTTP 模块,HTTP 处理器,或 ASP.NET 页面的代码分离文件。 .csproj,vbproj,vjsproj Visual Studio 工程目录。 Visual Studio 客户工程文件。 .disco,.vsdisco App_WebReferences 目录。 XML Web Services Discovery 文件。用于定位可用 Web Services。 .dsdgm,dsprototype 根目录或子目录。 分布式服务图表(DSD)文件。可添加到 Visual Studio 方案中,为反向引擎提供消耗 Web Services 时的交互性图表。 .dll Bin 目录。 已编译类库文件。作为替代,可将类对象源代码保存到 App_Code 目录。 .licx,.webinfo 根目录或子目录。 许可协议文件。许可协议有助于保护控件开发者的知识产权,并对控件用户的使用权进行验证。 .master 根目录或子目录。 模板文件定义 Web 页面的统一布局,并在其他页面中得到引用。 .mdb,.ldb App_Data 目录。 Access 数据库文件。 .mdf App_Data 目录。 SQLServer 数据库文件。 .msgx,.svc 根目录或子目录。 Indigo Messaging Framework(MFx)服务文件。 .rem 根目录或子目录。 远程处理器文件。 .resources App_GlobalResources 或 App_LocalResources 目录。 资源文件。包含图像,本地化文本,或其他数据的资源引用串。 .resx App_GlobalResources 或 App_LocalResources 目录。 资源文件。包含图像,本地化文本,或其他数据的资源引用串。 .sdm,.sdmDocument 根目录或子目录。 系统定义模型(SDM)文件。 .sitemap 根目录。 网站地图文件。包含网站的结构。ASP.NET 通过默认的网站地图提供者,简化导航控件对网站地图文件的使用。 .skin App_Themes 目录。 皮肤定义文件。用于确定显示格式。 .sln Visual Web Developer 工程目录。 Visual Web Developer 工程的项目文件。 .soap 根目录或子目录。 SOAP 扩展文件。 注意:ASP.NET 管理的文件类型映射到 IIS 的 Aspnet_isapi.dll。 2.IIS 管理的文件类型 在ASP.NET应用程序中,有些动态的文件如asp文件就不被ASP.NET应用程序框架管理,这些文件由IIS进行管理,由IIS管理的文件类型如表4-2所示。 表4-2 IIS管理的文件类型 文件类型 保存位置 描述 .asa 根目录。 Global.asa 文件。包含 ASP 会话对象或应用程序对象生命周期中的各种事件处理。 .asp 根目录或子目录. ASP Web 页面。包含 @ 指令和使用 ASP 内建对象的脚本代码。 .cdx App_Data 目录. Visual FoxPro 的混合索引文件。 .cer 根目录或子目录。 证明文件。用于对网站的授权。 .idc 根目录或子目录。 Internet Database Connector(IDC)文件。被映射到 httpodbc.dll。 注意:由于无法为数据库连接提供足够的安全性,IDC 将不再被继续使用。IIS 6.0 是最后一个支持 IDC 的版本。 .shtm,.shtml,.stm 根目录或子目录。 包含文件。被映射到 ssinc.dll。 注意:IIS管理的文件类型被映射到IIS的asp.dll 3.静态文件类型 IIS仅提供已注册MIME类型的静态文件服务,注册信息保存在Mime Map IIS元数据库中。如果某种文件类型已经映射到指定应用程序,在不需要作为静态文件的情况之下,无需再在MIME类型列表中进行包含。默认的静态文件类型如表4-3所示。 表4-3 静态文件类型 文件类型 保存位置 描述 .css 根目录或子目录,以及 App_Themes 目录。 样式表文件。用于确定 HTML 元素的显示格式。 .htm,.html 根目录或子目录。 静态网页文件。由 HTML 代码编写。 注意:虽然ASP.NET的代码页面也能够手动添加到MIME类型列表中,但是这样操作浏览者就能够看到页面源代码,从而暴露ASP.NET页面源代码,相对于服务器而言是非常不安全的。 4.8 小结 本章介绍了ASP.NET页面生命周期,以及ASP.NET页面的几种模型。ASP.NET页面生命周期是ASP.NET中非常重要的概念,熟练掌握ASP.NET生命周期能对ASP.NET开发,自定义控件开发起到促进作用。本章还介绍了: q 代码隐藏页模型的解释过程。 q 代码隐藏页模型的事件驱动处理。 q ASP.NET网页的客户端状态。 q ASP.NET页面生命周期。 q ASP.NET生命周期中的事件。 q ASP.NET 网站文件类型。 上面的章节都分开的讲解了ASP.NET运行中的一些基本机制,在了解了这些基本运行机制后,就能够在.NET框架下做ASP.NET开发了。虽然这些都是基本概念,但是在今后的开发中,会起到非常重要的作用。
Url重写系列篇: ----主讲:天涯浪子 本讲将通过实例比较ASP.NET下的三种典型URL重写方案——ISAPI重写(使用开源组件IIRF),ASP.NET2.0内置的urlMappings和基于自定义HTTPModule的URL重写(使用NBear.Web中的UrlRewriteModule实现),并探讨URL重写中可能遇到的陷阱及处理办法。 需要手动为UrlRewriteWebSite目录添加一个到http://localhost/UrlRewriteWebSite的同名虚拟目录,允许匿名访问,并设置目录默认页为default.aspx。 另外,为了启用IIRF的URL重写支持,需要将UrlRewriteWebSite/bin目录下的IsapiRewrite4.dll添加为IIS默认网站的ISAPI过滤器。[相应资料打压缩包] 重写原理: 用户(A)----->系统运行(C) 真实地址 用真实地址运行 用户(A)----->转换器(B)----->系统运行(C) 假地址 将用户假地址 用真实地址运行 转换为真实地址 重写规则 注意,我们的演示程序中将混合使用三种方式的URL重写,因此,需要为三种实现分别设置一些URL重写规则: 1、IIRF,对于IIRF,对应于IsapiRewrite4.dll,在相同的目录会有一个IsapiRewrite4.ini文件,除了默认的一些设置,我们在文件末尾添加了几条自定义规则如下: # Custom RewriteRules RewriteRule ^/UrlRewriteWebSite/test(.*).aspx /UrlRewriteWebSite/Default.aspx?page=$1 RewriteRule ^/UrlRewriteWebSite/folder/(.*).aspx /UrlRewriteWebSite/Default.aspx?folder=$1 RewriteRule ^/UrlRewriteWebSite/folder/? /UrlRewriteWebSite/Default.aspx?folder=default 熟悉正则表达式的朋友应该很容易理解上面这三条规则。 规则一将形如testXXX.aspx这样的页面访问,重写为Default.aspx?page=XXX这样的页面; 规则二将形如folder/XXX.aspx的路径,重写为Default.aspx?folder=XXX这样的页面; 规则三将不带任何文件的folder目录的访问,重写为Default.aspx?folder=default这样的页面。 2、urlMappings是ASP.NET2.0内置支持的URL重写配置块,它应该包含在web.config的配置块中。但是,这个内置的URL重写支持不支持正则表达式,因而只能用来实现一对一的路径和页面的重写。urlMappings的配置内容包含在下面的Web.config文件中。 3、NBear.Web.Modules.UrlRewriteModule则是NBear中实现的一个基于HTTPModule的URL重写实现,它允许使用正则表达式来描述重写规则。 注意,代码中包含了urlMappings配置和用于NBear.Web.Modules.UrlRewriteModule重写规则。为了比较着几种重写方案,正则表达式基本上是和前面的IIRF定义中的规则类似的。 页面测试 定义完这些重写规则,我们就可以试着在页面中使用它们了。例如,如果我们写一个测试页面如下: Default.aspx Default.aspx.cs public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Response.Write(Request.Path + "?" + Request.ServerVariables["QUERY_STRING"]); } } 注意,Default.aspx页面会输出当前呈现的实际页面及其QueryString参数。 运行该页面,分别点击页面中的链接,我们会看到,貌似所有的URL重写一切正常。但是,当试着点击页面中的按钮,我们马上会发现,页面postback后,浏览器地址栏中的链接变成了那个被重写后的地址,而不是,原来显示于地址栏的虚拟地址了。这是一个严重的不一致,没道理我点击页面的按钮,在没有跳转到其他页面的情况下,地址栏显示另一个页面地址,不是吗? 要解决这个问题,我们只需要为form添加一个onsubmit事件处理如下:
添加该事件处理,就能在页面postback提交之前,重置页面的地址。 为前面的页面添加onsubmit之后,我们发现,postback不再会改变地址栏地址显示了。 注意:你确认试过点击最后一组链接中的buildin default page和section default page了吗? 你会发现,这两个链接根本不能显示。为什么呢?为什么类似的folder default page可以正常显示,而另两个不能显示呢? 回到前面的规则定义部分,我们就能发现,folder default page使用的是由IIRF这个ISAPI定义的规则,而另两个则使用的是内置于ASP.NET2.0的HTTPModule的重写规则(本质上,urlMappings也是使用HTTPModule来实现重写的,所以,除了不支持正则表达式之外,它也包含自定义HTTPModule方式实现的所有缺点)。 在IIS的ISAPI层面,是可以截获所有的页面请求的,哪怕指定的页面、目录根本不存在。但是,ASP.NET解析器则只有在对页面的请求被IIS转发过来时,才能处理。我们知道,IIS可以忽略对链接的虚拟目录是否存在的检测,但是,却无法检测非ASP.NET支持的文件扩展名的链接(我们固然可以在IIS中将所有类型的扩展名都映射到ASP.NET解析器,但是,如果我们有设置IIS的权限,为什么还要用性能更低,限制更多的ASP.NET方式的URL重写,而不使用基于ISAPI方式的重写呢?)。所以,为了让这两个不能显示的页面能正常显示,一方面,我们要在IIS中设置默认页,如default.aspx,另一方面,需要让IIS对某个不带aspx扩展名的链接,如这里只包含某个目录的名称的链接转发到默认页。 要做到这一点,我们需要在我们的应用程序中,为buildin和section分别将两个对应的目录,并且,在目录中创建两个空的default.aspx页面。尽管这样的default.aspx页面实际上永远不会被真正执行,但是有他们的帮助,就能让IIS顺利地将页面请求转发至ASP.NET解析器,从而,使得基于HTTPModule的URL重写规则,被执行。 好了,创建这两个目录及default.aspx文件,我们就能修复该问题了。 接下来我们先做点测试: 我们来对页面上的链接反复点击点击,folder page -> section page -> folder page -> section page...等等,打住,看到浏览器地址栏发生了什么吗?这不是恐怖活动,但是。。。也差不多了。我们看到我们可爱的地址,变成了...folder/section/folder/section...aspx。 想想是为什么呢?看看我们的aspx文件。。。我想你一定想到了。对了,都是相对路径惹的祸! 我们可爱的的相对路径一顶是同学们最常使用的,但是,浏览器在处理相对路径时,是以浏览器上接受的url地址为基础进行计算的,也就是说,如果当前的地址为folder/1.aspx,那么,很显然,./section/2.aspx这个页面,对应的自然是folder/section/2.aspx了,问题就出在这儿了!没有URL重写时,不会有这样的情况出现。但是URL重写,并且,将一个带假目录的虚拟地址重写到一个不带假目录的页面时,由于浏览器客户端和服务端此时的当前页面计算方法是不同的,就会发生相对路径的匹配错误问题!真实很严重的问题啊! 解决的办法,只有使用绝对路径!但是,我们当然不会傻到对每个链接直接使用绝对路径的,呵呵:) 将Default.aspx中的所有相对路径都使用Page.ResolveUrl进行包装如下,在输出页面时就将地址转换为绝对路径,就能解决这个恐怖的相对路径陷阱了。当然,也别忘了加上onsubmit事件处理代码: Default.aspx 好了,再试一试点击页面上的链接和按钮,多点几次 谢谢………… 参考资料: 引言 让我们花点时间来看一下网站上的一些 URL。您是否发现一些类似于 http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&type=summary 的 URL?或者,您可能将一系列网页从一个目录或网站移动到另一个目录或网站,结果导致已将旧 URL 用作书签的访问者断开链接。在本文中,我们将了解如何通过将 http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&type=summary 替换为类似于 http://yoursite.com/people/sales/chuck.smith 的网址,使用 URL 重写将那些冗长的 URL 缩写为富有意义且容易记忆的 URL。我们还将了解如何将 URL 重写用于创建智能 404 错误。 URL 重写是截取传入 Web 请求并自动将请求重定向到其他资源的过程。执行 URL 重写时,通常会检查被请求的 URL,并基于 URL 的值将请求重定向到其他 URL。例如,在进行网站重组而将 /people/ 目录下的所有网页移动到 /info/employees/ 目录中时,您可能希望使用 URL 重写来检查 Web 请求是否指向了 /people/ 目录中的文件。如果请求指向 /people/ 目录中的文件,您可能希望自动将请求重定向到 /info/employees/ 目录中的同一文件。 使用传统的 ASP,应用 URL 重写的唯一方法是编写 ISAPI 筛选器,或者购买提供 URL 重写功能的第三方产品。但是,使用 Microsoft® ASP.NET,您可以通过很多方法来轻松地创建您自己的 URL 重写软件。本文讨论了可供 ASP.NET 开发人员实现 URL 重写的各种技术,然后讨论了 URL 重写的一些实际使用情况。在深入讨论 URL 重写的技术细节之前,让我们先看一些可以使用 URL 重写的日常情景。 URL 重写的常见用法 创建数据驱动的 ASP.NET 网站时,通常会产生一个单个的网页,该网页基于查询字符串参数显示数据库数据的子集。例如,在设计电子商务站点时,您的任务之一便是允许用户浏览待售产品。为此,您可以创建一个名为 displayCategory.aspx 的页面,该页面将显示给定类别的产品。可以通过查询字符串参数来指定要查看的该类别的产品。也就是说,如果用户要浏览待售的 Widget 产品,并且所有 Widget 产品的 CategoryID 均为 5,则用户可以访问以下网址:http://yousite.com/displayCategory.aspx?CategoryID=5。 创建具有此类 URL 的网站有两点不足:首先,从最终用户的角度考虑,URL http://yousite.com/displayCategory.aspx?CategoryID=5 比较杂乱。可用性专家 Jakob Neilsen 建议遵循以下标准来选择 URL: • 简短。 • 易于键入。 • 可以看出站点的结构。 • “可删节”,允许用户通过删除 URL 的组成部分来浏览站点。 我还要增加一条标准,即,URL 应该便于记忆。URL http://yousite.com/displayCategory.aspx?CategoryID=5 不符合 Neilsen 的任何标准,也不容易记住。要求用户键入查询字符串值将使 URL 的键入变得非常困难,并且只有了解查询字符串参数的用途及其名称/值对结构的富有经验的 Web 开发人员才能够对 URL 进行“删节”。 较好的方法是允许使用切合实际且容易记忆的 URL,如 http://yoursite.com/products/Widgets。只要看一眼 URL,您便可以推断出将要显示的内容 -- 有关 Widget 的信息。此 URL 也很容易记住和共享。我可以告诉我的同事“请查看 yoursite.com/products/Widgets,”,她可能无需再次问我 URL 是什么即可打开该页面。(尝试一下,您只需说出“Amazon.com 页面”即可!)此 URL 还将显示出来,并且应该是“可删节”的。也就是说,如果用户删去 URL 的末端,键入 http://yoursite.com/products,他们应该看到所有产品的列表,或者至少应该看到他们可以查看的所有类别的产品列表。 注意:要获得“可删节”URL 的最好示例,可考虑使用由许多 blog 引擎生成的 URL。要查看 2004 年 1 月 28 日的帖子,用户可以访问诸如 http://someblog.com/2004/01/28 的 URL。如果该 URL 被删节为 http://someblog.com/2004/01,用户将看到 2004 年 1 月的所有帖子。将该 URL 进一步删节为 http://someblog.com/2004 将显示 2004 年的所有帖子。 除了简化 URL 之外,URL 重写还经常用于处理网站重组,以免导致大量链接断开或书签过期。 请求到达 IIS 时将会发生什么情况 在正式研究 URL 如何实现重写之前,应首先了解 Microsoft® Internet Information Services (IIS) 如何处理传入请求,这一点非常重要。当请求到达 IIS Web 服务器时,IIS 检查被请求文件的扩展名以确定如何处理该请求。IIS 可以自行处理请求(如 HTML 页面、图像以及其他静态内容),或者将请求路由到 ISAPI 扩展。(ISAPI 扩展是一个处理传入 Web 请求的非托管编译类。其任务是生成被请求资源的内容。) 例如,当传入针对 Info.asp 网页的请求时,IIS 会将此消息路由到 asp.dll ISAPI 扩展。然后,该 ISAPI 扩展将加载被请求的 ASP 页面,执行该页面,并将所呈现的 HTML 返回给 IIS,然后,IIS 将该 HTML 发送回请求客户端。对于 ASP.NET 页面,IIS 会将此消息路由到 aspnet_isapi.dll ISAPI 扩展。然后,aspnet_isapi.dll ISAPI 扩展将处理操作传递给托管的 ASP.NET 辅助进程,该辅助程序将处理请求,并返回 ASP.NET 网页的呈现 HTML。 您可以自定义 IIS,以指定扩展名与 ISAPI 扩展的映射关系。图 1 显示了 Internet Information Services 管理工具的“应用程序配置”对话框。请注意,与 ASP.NET 有关的扩展名(.aspx、ascx、config、asmx、rem、cs、vb 及其他)均已映射到 aspnet_isapi.dll ISAPI 扩展。 图 1. 已配置的文件扩展名映射 讨论 IIS 如何管理传入请求稍稍超出了本文范围。但是可以在 Michele Leroux Bustamante 的文章 Inside IIS and ASP.NET 中找到对此内容的深入讨论。ASP.NET 引擎仅处理那些扩展名已明确映射至 IIS 中的 aspnet_isapi.dll 的传入 Web 请求,了解这一点非常重要。 使用 ISAPI 筛选器检查请求 IIS 除了可以将传入 Web 请求的文件扩展名映射到相应的 ISAPI 扩展之外,还将执行许多其他任务。例如,IIS 将尝试对发出请求的用户进行身份验证,并确定通过身份验证的用户是否有权限访问被请求的文件。在处理请求的有效期内,IIS 将经历几个状态。在每个状态下,IIS 都将引发可以使用 ISAPI 筛选器以编程方式进行处理的事件。 与 ISAPI 扩展一样,ISAPI 筛选器是在 Web 服务器上安装的非托管代码块。ISAPI 扩展被设计为可以响应针对特定文件类型的请求。另一方面,ISAPI 筛选器还包含可以对 IIS 引发的事件进行响应的代码。ISAPI 筛选器可以截取甚至修改传入和传出的数据。ISAPI 筛选器可以应用于很多方面,包括: • 身份验证和授权。 • 记录和监视。 • HTTP 压缩。 • URL 重写。 虽然 ISAPI 筛选器可用于执行 URL 重写,但本文将讨论如何使用 ASP.NET 实现 URL 重写。不过,我们将对使用 ISAPI 筛选器与使用 ASP.NET 中的技术实现 URL 重写进行权衡。 请求进入 ASP.NET 引擎时将会发生什么情况 在 ASP.NET 之前,需要使用 ISAPI 筛选器来实现 IIS Web 服务器上的 URL 重写。由于 ASP.NET 引擎与 IIS 非常相似,因此可以使用 ASP.NET 进行 URL 重写。存在相似之处的原因在于 ASP.NET 引擎可以实现以下功能: • 在处理请求时可以引发事件。 • 允许任意数量的 HTTP 模块处理所引发的事件,这与 IIS 的 ISAPI 筛选器相似。 • 将呈现被请求资源这项任务委托给 HTTP 处理程序,该处理程序与 IIS 的 ISAPI 扩展相似。 与 IIS 一样,ASP.NET 引擎在请求的有效期内将会触发事件,通过发信号来表示其处理过程从一个状态改变为了另一个状态。例如,当 ASP.NET 引擎首次响应请求时,BeginRequest 事件将被触发。接下来触发的是 AuthenticateRequest 事件,该事件在已建立用户标识时出现。(此外,还有大量的其他事件:AuthorizeRequest、ResolveRequestCache 和 EndRequest,等等。这些事件属于 System.Web.HttpApplication 类;有关详细信息,请参阅位于以下网址的技术文档:HttpApplication Class Overview。) 正如上一部分所讨论的,可以创建 ISAPI 筛选器以响应 IIS 引发的事件。同样,ASP.NET 提供了 HTTP 模块,该模块可以响应由 ASP.NET 引擎引发的事件。可以将 ASP.NET Web 应用程序配置为具有多个 HTTP 模块。对于由 ASP.NET 引擎处理的每个请求,将初始化每个已配置的 HTTP 模块,并允许将事件处理程序绑定到处理请求期间所引发的事件。请注意,对每个请求均使用了许多内置 HTTP 模块。其中的一个内置 HTTP 模块是 FormsAuthenticationModule,该模块首先检查是否使用了窗体身份验证,如果使用,将检查是否对用户进行了身份验证。如果没有使用,会自动将用户重定向到指定的登录页面。 如上所述,通过使用 IIS,传入请求将最终发送给 ISAPI 扩展,而 ISAPI 扩展的任务是返回特定请求的数据。例如,在请求传统的 ASP 网页时,IIS 将请求传递给 asp.dll ISAPI 扩展,该扩展的任务是返回被请求的 ASP 页面的 HTML 标记。ASP.NET 引擎使用相似的方法。初始化 HTTP 模块后,ASP.NET 引擎的下一项任务是确定应由哪个 HTTP 处理程序来处理请求。 所有通过 ASP.NET 引擎传递的请求最终都将到达 HTTP 处理程序或 HTTP 处理程序工厂(HTTP 处理程序工厂仅返回 HTTP 处理程序的实例,然后使用该实例来处理请求)。最终的 HTTP 处理程序将返回响应,即呈现被请求的资源。此响应将被发送回 IIS,然后 IIS 将响应返回给提出请求的用户。 ASP.NET 包括许多内置的 HTTP 处理程序。例如,PageHandlerFactory 用于呈现 ASP.NET 网页。WebServiceHandlerFactory 用于呈现 ASP.NET Web 服务的响应 SOAP 信封。TraceHandler 将向 trace.axd 呈现请求的 HTML 标记。 图 2 描述了如何处理对 ASP.NET 资源的请求。首先,IIS 接收到请求,并将请求调度给 aspnet_isapi.dll。接下来,ASP.NET 引擎对已配置的 HTTP 模块进行初始化。最后将调用正确的 HTTP 处理程序,并呈现被请求的资源,将所生成的标记返回给 IIS 和请求客户端。 图 2. IIS 和 ASP.NET 正在处理请求
c#学习笔记(1) 51099在线学习网发布 文章来源:网络收集 发布时间:2006-05-25 字体: [大 中 小] 51099在线学习网 http://www.51099.com 1, 结构(struct) 与 类(class) [attributes] [modifiers] struct identifier [:interfaces] body [;] 结构与类很相似,都表示可以包含数据成员和函数成员的数据结构。与类不同的是,结构是值类型并且不需要堆分配。结构类型的变量直接包含结构的数据,而类类型的变量包含对数据的引用(该变量称为对象)。 struct 类型适合表示如点、矩形和颜色这样的轻量对象。尽管可能将一个点表示为类,但结构在某些方案中更有效。在一些情况下,结构的成本较低。例如,如果声明一个含有 1000 个点对象的数组,则将为引用每个对象分配附加的内存。结构可以声明构造函数,但它们必须带参数。声明结构的默认(无参数)构造函数是错误的。总是提供默认构造函数以将结构成员初始化为它们的默认值。在结构中初始化实例字段是错误的。在类中,必须初始化实例对象. 使用 new 运算符创建结构对象时,将创建该结构对象,并且调用适当的构造函数。与类不同的是,结构的实例化可以不使用 new 运算符。如果不使用 new,那么在初始化所有字段之前,字段将保持未赋值状态且对象不可用。对于结构,不像类那样存在继承。一个结构不能从另一个结构或类继承,而且不能作为一个类的基。但是,结构从基类 Object 继承。结构可实现接口,其方式同类完全一样。 [c ] 与 C 不同,无法使用 struct 关键字声明类。在 C# 中,类与结构在语义上是不同的。结构是值类型,而类是引用类型。 2, 装箱和拆箱(取消装箱) 装箱是值类型到 object 类型或到该值类型所实现的任何接口类型的隐式转换。将一个值的值装箱会分配一个对象实例并将该值复制到新的对象中。关键字 object. 取消装箱是从 object 类型到值类型或从接口类型到实现该接口的值类型的显式转换。取消装箱操作包括:检查对象实例,确保它是给定值类型的一个装箱值。将该值从实例复制到值类型变量中。 例: int i = 123; // A value type object box = i; // Boxing int j = (int)box; // Unboxing 装箱转换 取消装箱 3 , 隐式和显式 下列转换属于隐式转换:例:object o=i; 标识转换。 隐式数值转换。 隐式枚举转换。 隐式引用转换。 装箱转换。 隐式常数表达式转换。 用户定义的隐式转换。 下列转换属于显式转换: object 0=(object)i; 所有隐式转换。 显式数值转换。 显式枚举转换。 显式引用转换。 显式接口转换。 取消装箱转换。 用户定义的显式转换 4, delegate(委托) delegate void D(int x); class C{ public static void M1(int i) { /* ... */ } public static void M2(int i) { /* ... */ }} class{…….D cd1 = new D(C.M1);………….} 委托是一个数据结构,该数据结构引用一个静态方法,或引用一个对象实例和该对象的实例方法。在 C 或 C 中与委托最接近的是函数指针,但函数指针只能引用静态函数,而委托可以同时引用静态方法和实例方法。在后一种情况中,委托不仅存储对方法入口点的引用,还存储对调用其方法的对象的引用。与 C 函数指针不同,委托是完全面对对象的;与指向成员函数的 C 指针不同,委托同时封装对象实例和方法。委托声明定义从类 System.Delegate 派生的类。委托实例封装一个或多个方法,每个方法都被称为可调用实体。对于实例方法,可调用实体由一个实例和该实例上的方法组成。对于静态方法,可调用实体仅由一个方法组成。给定委托实例和适当的参数集,便可以用该参数集调用此委托实例的所有方法。委托实例的一个有趣和有用的属性是它不了解或不关心它所封装的方法的类;真正重要的只是方法要与委托的类型兼容, 这使委托非常适合“匿名”调用。可选的形参表指定委托的参数,而返回类型则指示委托的返回类型。如果下面两个条件都为真,则方法和委托类型是兼容的:(兼容的概念就是可以用此声明的委托对方法进行委托). 1它们具有相同的参数数目,并且类型相同,顺序相同,参数修饰符也相同。 2它们的返回类型相同。 C# 中的委托类型是名称等效的,而不是结构等效的。(但是请注意:两个不同但结构上等效的委托类型的实例可能会比较为相等),准确地说,两个具有相同参数列表、签名和返回类型的不同的委托类型被认为是不同的委托类型。委托实例所封装的方法集合称为调用列表。 5, interface(接口) [attributes] [modifiers] interface identifier [:base-list] {interface-body}[;] 一个接口定义一个协定。实现接口的类或结构必须遵守其协定。接口可以从多个基接口继承,而类或结构可以实现多个接口。接口可以包含方法、属性、事件和索引器。接口本身不提供它所定义的成员的实现。接口只指定实现该接口的类或接口必须提供的成员。接口可以是命名空间或类的成员,并且可以包含下列成员的签名:方法属性 索引器. 一个接口可从一个或多个基接口继承。接口可由类实现。实现的接口的标识符出现在类的基列表中。被继承的接口称为该接口的显式基接口。当接口具有一个或多个显式基接口时,在该接口声明中,接口标识符后跟一个冒号以及由逗号分隔的基接口标识符列表。接口的基接口是显式基接口及其基接口。换言之,基接口集是显式基接口、它们的显式基接口(依此类推)的完全可传递的闭包。接口继承其基接口的所有成员。接口成员是通过 I.M 和 I[A] 形式的成员访问和索引访问表达式访问的,其中 I 是接口类型的实例,M 是该接口类型的方法、属性或事件,A 是索引器参数列表。接口可以由类和结构实现。为了指示类或结构实现接口,在该类或结构的基类列表中包含了接口标识符。在实现类或结构中定位接口成员的实现的过程称为接口映射。 6,object object 类类型是所有其他类型的最终基类。C# 中的每种类型都是直接或间接从 object 类类型派生的。可以把任何类型的数值给object类型. 7,string类型 string 类的实例表示 Unicode 字符串。尽管 string 是引用类型,但相等运算符(== 和 !=)被定义为比较 string 对象(而不是引用)的“值”(7.9.7 字符串相等运算符)。这使得对字符串相等性的测试更为直观。字符串为 string 类型并可写成两种形式,即用引号引起来和用 @ 引起来。用引号引起来的字符串括在双引号 (") 内, 并且可以包含包括换码序列在内的任何字符用 @ 引起来的字符串以 @ 开头,并用双引号引起来。用 @ 引起来的字符串以 @ 开头,并用双引号引起来。若要在一个用 @ 引起来的字符串中包括一个双引号,请使用两对双引号:@ 符号的另一种用法是使用碰巧成为 C# 关键字的被引用的 (/reference) 标识符。 8, 修饰符 修饰符作用 访问修饰符 public private internal protected 指定声明的类型和类型成员的可访问性。 访问不受限制 只有包含该类的成员的类可以访问 只有当前工程可以访问 只有包含该成员的类和继承的类可以访问 abstract指示某个类只能是其他类的基类。 const指定无法修改字段或局部变量的值。 event声明一个事件。 extern指示外部实现此方法。 override提供从基类继承的虚拟成员的新实现。 readonly声明一个字段,该字段只能赋值为该声明的一部分或者在同一类的构造函数中。 sealed指定类不能被继承。 static声明属于类型本身而不是属于特定对象的成员。 unsafe声明不安全的上下文。 virtual在派生类中声明其实现可由重写成员更改的方法或访问器。 volatile指示字段可由操作系统、硬件或并发执行的线程等在程序中进行修改。 9,语句 语句是程序指令。除非特别说明,语句都按顺序执行。C# 具有下列类别的语句。 类别C# 关键字 选择语句if, else, switch, case 迭代语句do, for, foreach, in, while 跳转语句break, continue, default, goto, return 异常处理语句throw, try-catch, try-finally Checked 和 Uncheckedchecked, unchecked fixed 语句Fixed lock 语句Lock (1) foreach 语句为数组或对象集合中的每个元素重复一个嵌入语句组。foreach 语句用于循环访问集合以获取所需信息,但不应用于更改集合内容以避免产生不可预知的副作用。此语句的形式如下: foreach (type identifier in expression) statement 若要循环访问集合,集合必须满足特定的要求。集合类型: 必须是 interface、class 或 struct。 必须包括返回类型的名为 GetEnumerator 的实例方法,例如 Enumerator(详见下文)。 Enumerator 类型(类或结构)必须包含: 一个名为 Current 的属性,它返回 ItemType 或者可以转换为此类型的类型。属性访问器返回集合的当前元素。 · 一个名为 MoveNext 的 bool 方法,它递增项计数器并在集合中存在更多项时返回 true。 有三种使用集合的方法: 使用上述指导创建一个集合。此集合只能用于 C# 程序。 1. 使用上述指导创建一个一般集合,另外实现 IEnumerable 接口。此集合可用于其他语言(如 Visual Basic)。 2. 在集合类中使用一个预定义的集合。 (2) throw 语句用于发出在程序执行期间出现反常情况(异常)的信号。throw 语句的形式为: throw [expression]; expression :异常对象。当在 catch 子句中再次引发当前异常对象时,它被省略。 (3)try –catch语句 try-catch 语句由一个 try 块和其后所跟的一个或多个 catch 子句(为不同的异常指定处理程序)构成。try-catch 语句采用下列形式之一: try try-block catch (exception-declaration-1) catch-block-1 catch (exception-declaration-2) catch-block-2 ... try try-block catch catch-block (4) fixed 防止变量被垃圾回收器重定位。 (5) lock lock 关键字将某个语句块标记为临界区。 6. 方法参数 如果为没有 ref 或 out 的方法声明一个参数,则此参数可以具有关联的值。可以在方法中更改该值,但当控制传递回调用过程时,不会保留更改的值。通过使用方法参数关键字,可以更改这种行为。如果没有ref,out则默认为值传递,虽然可以在方法中修改这个参数的值,但是修改后的值不会还会到调用该方法的程序中. params :params 关键字可以指定在参数数目可变处采用参数的方法参数 ref :引用传递 out : 7, namespace(名字空间) C#学习笔记(2)【大 中 小】【打印】【加入收藏】【关闭】 【收藏到新浪ViVi】【收藏到365KEY】 浏览字号:日期:2004-07-11 人气:8092 出处: write by cash(天下第七) 2002.01.20 版权所有,翻录不究 cashcao@msn.com 选择 我身上携带着精神、信仰、灵魂 思想、欲望、怪癖、邪念、狐臭 它们寄生于我身体的家      我必须平等对待我的每一位客人 -----------伊沙:《原则》 我的名字是cash,所以我很功利主义; 我的星像是Leo,所以我很大男人主义; 我的语言是C#,所以我有点儿拿不定主义。 /* 你能看得出来,这不是一篇正规的技术文章,所以若你不小心从里边读到了一个爱情故事,可不要奇怪。有很多人用程序来表述爱情,在其中我能看到有Money,有Girl,有一些还涉及到Sex,但是我没有找到Love,我始终相信这世上有一种力量直接来自于爱情,到现在仍然相信。*/ C#(读作C sharp),是Microsoft公司新推出的(?)专为.NET设计的一门语言,号称“C/C++家族中第一种面向组件的语言”。很多人觉得它应该像C或者C++,但事实上它更像是java的一个clone,所以作为入门,读一下清华大学出版社出版的《Java 语言与面向对象程序设计》可能会对你有所帮助。本文假定你具备一切学习此语言所需的知识,没有也不要紧,我会在文中尽量列出相关的link,鉴于互联网瞬息万变的特点,若某一链接不可用,请自行至Google查询。 如前所述,我是一个狮子座男人,一度我认为学习Java会使我看起来与众不同,可是几个月以后我放弃了这个选择,我看了论坛里关于这两种语言孰优孰劣的讨论,最终选择了C#,请不要问我为何做出这样的选择,很多人认为中文是世界上最美丽的语言,可是华人世界以外有谁在讲汉语? 另外我发现论坛上学习Java的人都非常的有个性,当有人问起学习哪种语言更好时,他会打出几百个“JAVA”来,填满整个屏幕,也不说是为了什么。我觉得这样做未免有些太霸道了,如果你说这叫偏执狂我也不反对,虽然我是狮子座,可也不想被人这样看。 在C#刚刚推出的时候,大多数的程序员都不免吼上两句——不是因为高兴,而是因为又多了一种语言。他们觉得现在的语言太多了,没有必要再多出一种来添乱子。但是当他们看完C#的文档后又开始高兴起来,因为C#是如此简单:事实上,简单正是C#最大的特点。除此之外,它还具有现代、面向对象、类型安全、版本控制、兼容、灵活等特点。详细介绍请参阅rainbow(一个长着胡子的彩虹)翻译的<> ,前几章非常的有趣。 看完了前面几段,我的朋友提出了不同的意见:C#不是Java的Clone,它只是长得有些像Java而已,其实面向对象、中间语言什么的也不是什么新玩意儿,非Sun独创,有文为证:华山论剑:C#对Java。另外他对我上一集中说Microsoft越来越不要脸也极为生气,因为相比之下,Sun也不怎么样,微软已经将C#提交设在日内瓦的ECMA(European Computer Manufacturers' Association,国际标准化机构欧洲电子计算机工业会)并获得批准。Sun就从来没有将它的Java交给过ECMA,以至于正当Microsoft尽力在Visual J++基础上拓展Java功能,并使之与Windows操作系统紧密结合在一起的时候,Sun公司对Microsoft提出了法律诉讼,控告Microsoft违反了许可证协议中的条款,最终的结果是Microsoft公司不得不停止其Visual J++产品的开发。(Microsoft后来在完全面向.NET框架的开发语言集中加入了Visual J#.NET,算是对Java语言用户的一种照顾。) 有人说,选择C#意味着选择MS(在中国的程序员当中,这并不是件值得自豪的事。如果你还不能理解这种心情,可以试想一下有人很认真地对你讲他喜欢听毛宁的歌)。事实上,通过ECMA标准的C#可以由任何人在任何平台上设计出它的开发程序。比如Ximian公司的Mono工程,可以使开发者能够编写同时在Windows和Linux上运行的.Net程序,这些程序甚至还可能在其它非Windows的操作系统上运行,比方Unix。这一段时间我正在Linux下试验这个工程,遗憾的是,还没有成功。 一位师兄对此种比较颇为不屑,他认为只要选一种语言去学就好了,“重要的是你要用它,并且做的比别人好。”这让我想起来一直都很喜欢的那个歌:把你自己该做的那份工作,做得比别人出色。年轻的时候我老是用这句话自勉…… 写到这里我发现这个故事还没有提到桐桐,这篇东西是为她而作。我早在十八个月以前就答应了她,我答应了她很多事,但还没有完成一件,现在我要一件一件的去实现。所以这个故事还应该有个更好的开始。 2000年6月我大学毕业,从北京回到了石家庄,到一家什么都做的公司上班(做一个网站),最开始制作界面,然后用asp编程,如果你用过asp就会知道,这是个很无聊的工种。在此之前我在一家报社实习,为他们的网站做设计和动画。在那里我认识了桐桐。 那时候她还在上学。 >>>未完,待续... C#学习笔记(3)【大 中 小】【打印】【加入收藏】【关闭】 【收藏到新浪ViVi】【收藏到365KEY】 浏览字号:日期:2004-07-11 人气:6938 出处: 开始 2000年6月我大学毕业,从北京回到了石家庄,正式开始了我的职业生涯。如前所述,一开始我使用的语言是asp,我一直认为这不能称之为编程,因为asp不是一种编程语言,把它叫做动态网页实现技术可能更好。另外,asp很简单,并且,简单就是它全部的特点--这使得它很容易就能学会(在后来的工作中,我接触到许多应聘的学生,他们都告诉我自己精通asp语言)。虽然学习起来很简单,但是在使用起来却不得不多费点儿劲儿:我还能记得自己晚上一个人在办公室用VI一步一步调试某一个网页的情景,每当遇到挫折失败的时候,总是想起给桐桐打一个电话,听听她的声音。如你所知,我总是遇到困难。 现在你能看出来,我不是高手,只是一个低手... 2000年6月我大学毕业,从北京回到了石家庄,同一时间(美国西部时间6月22日上午),微软公司在位于美国西雅图郊外的总部内邀请新闻记者、新闻分析家等约400人,举行了新闻发布会“Forum2000”,宣布正式推出.Net计划。这个计划中包括了新的网络计算平台(.Net Framework)、新的语言(C#)、新的开发工具(Visual Studio.Net)以及asp的下一个版本ASP.NET,后者最开始被称为ASP+。那时候我学习的主要兴趣就在ASP.NET上,并且通过这个窗口开始了解Microsoft.Net的各个方面。 ASP.NET仍然不能称之为一种编程语言,但是现在可以把它看作是一个创建、管理、部署Web应用程序的平台。可以使用任何.Net语言在这个平台上开发互联网应用程序,这其中当然包括C#。它们之间的关系可以从下图中看出: 这就是著名的.Net 平台结构图,从这个图上可以看到,ASP.NET、Windows Forms和VS.Net都不过是.Net开发平台的一部分,用于.Net应用程序的开发及展示。.Net 平台的核心技术为:通用语言运行时(CLR:Common Language Runtime)、基类库(Base Class Library)、.Net语言及Visual Studio.Net。 从这个图上也可以看出,.Net Framework是架构在Windows平台上的一个虚拟的运行平台,你可以想象将最下层的Windows换作其它的操作系统,比如说Linux,一样可以实现使用符合了CLS(Common Language Specification,通用语言规范)的.Net语言(VB.Net、C#、JScript.Net等)来创建ASP.NET或Windows Forms(可能会叫做Linux Forms)应用程序的功能,这其实就是我们前面介绍的Mono计划所要实现的功能。所以可以这么认为,理论上,C#是一种可以跨平台的语言,这很像Java,另一个比较像Java的地方是,C#也是一种(特殊意义上的)解释性的语言。同Java一样,C#编写的程序代码也是先通过C#编译器编译为一种特殊的字节代码(中间语言,Microsoft Intermediate Language,MSIL),运行的时候再经由特定的编译器(JIT编译器,Just In Time,JITer)编译为机器代码以供操作系统执行。 不仅是C#语言,所有.Net语言(将会包括我们常用的几十种现代的编程语言)都可以编写面向CLR的程序代码,这种代码在.Net中被称为托管代码(Managed Code),所有的Managed Code都直接运行在CLR上,具有与平台无关的特性。 解释性的语言很安全,并且可以通过它的运行平台为其赋予更多的功能,比如自动内存管理、异常处理等。事实上,C#语言的许多特点都是由CLR提供的,下面的CLR结构图说明了这一点。 可以看到,类型安全(Type Checker)、垃圾回收(Garbage Collector)、异常处理(Exception Manager)、向下兼容(COM Marshaler)、多线程支持(Thread Support)这些C#的特点都是由CLR来提供的。CLR最早被称为下一代Windows服务运行时(NGWS Runtime),是直接建立在操作系统层上的一个虚拟的运行环境,主要的功能是管理代码的运行。在.Net 平台结构图中,CLR的上面是.Net的基类库(Base Class Library,BCL),这组基类库包括了从基本输入输出到数据访问等各方面,提供了一个统一的面向对象的、层次化的、可扩展的编程接口。从.Net 平台结构图中也可以看到,基类库可以被各种语言调用和扩展,也就是说,不管是C#、VB.NET还是VC++.NET,都可以自由地调用.Net的基类库。事实上, C#并没有属于自己的类库,它所使用的编程接口就是.Net提供的基类库。所以,在决定使用C#时,真正需要费工夫学习的其实是.NET框架的基类库:C#自身只有区区77个关键词,而且其语法对许多程序员来说都是他们非常熟悉的。BCL则相反,它包含了超过4500个以上的类和无数的方法、属性,在你的C# 程序中随时都可能会用到它来完成自己的任务。 很多人都思考过应如何开始学习一种新的语言,对于一个有经验的编程人员来讲,这确非难事。但是对于一个对编写代码一无所知的人而言,如果你是以C#开始你的编程之旅的,数目繁多的概念及新名词可能会令你有些不知所措。这时候请注意你的学习顺序,任何一种编程语言的学习都是按照运行平台、语法、基类库直至各方面的应用这一顺序来进行的,但是在实际的学习中,它们之间并不是孤立的。推荐的方法是:对运行平台和语法有了一个整体的认识后,在应用中学习各种基类库的用法。鉴于C#这一语言的特殊性,全面了解它的运行平台(.Net Framework)必会使你的学习事半功倍。所以请记住上面提到的两个图,在以后的学习中,虽然可能不会明确的涉及到它们,但是在整个C#的学习过程中,它们却是无处不在的。 还有一个很重要的概念需要你明白,这就是公共语言架构(Common Language Infrastructure ,CLI)。CLI是CLR的一个子集,也就是.NET中最终对编译成MSIL代码的应用程序的运行环境进行管理的那一部分。在CLR结构图中CLI位于下半部分,主要包括类加载器(Class Loader)、实时编译器(IL To Native Compilers)和一个运行时环境的垃圾收集器(Garbage Collector)。CLI是.Net和CLR的灵魂,CLI为IL代码提供运行的环境,你可以将使用任何语言编写的代码通过其特定的编译器转换为MSIL代码之后运行其上,甚至还可以自己写MSIL代码在CLI上面运行。如你所知,欧洲计算机制造商协会(ECMA)已经于2001年10月13日批准C#语言规范(ECMA-334)成为一种新诞生的计算机产业标准。同时国际标准组织ISO也同意该标准进入该组织的审批阶段。并且,作为.Net与CLR的核心部分,CLI与C#也同时获得了ECMA的批准(ECMA-335)。拥有了C#与CLI这两项标准,你可以自己写出能够运行于任何操作系统上的.Net平台(只要你愿意)。如前所述,著名的Mono项目就是这么干的,Mono项目包括三个核心的部分:一个C#语言的编译器,一个CLI和一个类库。在Java的世界中,这项工作是由SUN公司完成的,SUN针对不同的操作系统开发出相应的Java虚拟机以便让一个由Java开发的应用程序运行在不同的操作系统上,但是迄今为止还没听说过微软有这方面打算(为用户提供非Windows系统的.Net平台)。 2000年的6月还有很多事情发生,2000年的6月我在学校做毕设,晚上就跑到系试验室看欧锦赛,我很喜欢的坎普君(Bergkamp)大放异彩,帮助荷兰队6比1大胜南斯拉夫,米哈伊洛维奇 (Mihajlovic)在比赛最后莫名的笑容永远留在了我的心中。说实话,那时候只顾着看EURO2000,可没管什么.Net、.Not。另外,离别的愁绪围绕在每个人的周围,广播里开始反反复复播放一些古老的歌曲,不知道为什么,恋曲1980却是那时候的最爱。 后来,我们都毕了业。如你所知,我离开了北京。 >>>未完,待续... C#学习笔记(4)【大 中 小】【打印】【加入收藏】【关闭】 【收藏到新浪ViVi】【收藏到365KEY】 浏览字号:日期:2004-07-11 人气:8360 出处: 约定 //一个典型的用C#写就的HelloWorld程序 using System; class HelloWorld { public static void Main() { Console.WriteLine("Hello World !"); } } 我忘记自己第一次用C#向世界问好是在什么时候了,不过可以肯定我已经打过招呼了,那时候用的是beta1版。现在你可以到http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/000/976/msdncompositedoc.xml去下载.Net Framework Software Development Kit (SDK)的正式版,其中包括了前面提到的.NET Framework, 以及书写、编译、测试、开发 .NET Framework 应用程序所需要的一切——文档、例子、命令行工具和编译器。安装之后就可以开发和运行C#程序了,不过一般的建议是:一定要看.Net Framework SDK中所带的文档与例子,如果能照着例子再写一遍那就再好不过了。 当我第一次看到C#代码的时候,同样认为它很像Java,一个形象的比喻是:C#和Java是一对双胞胎,从语法的角度来讲,它们共同的父亲当然非C++莫属(请注意,不是VC++)。对于一个学过Java语言的人来说(比如说在下),要理解这段代码实在是太容易了:第一行当然是注释了,C#支持两种注释方法,以"//"开始的单行注释和以"/*"、"*/"配对使用的多行注释。第二行(using System)导入了System这个包(在C#中被称之为名字空间,Namespace),可以让我们方便的调用Microsoft.Net基类库System中的所有类,在此例中使用了System名字空间中的"Console"类,用于在控制台窗口输出程序运行结果。如前所述,C#并没有内置的输入输出语句,所有需实现的功能都完全来自于.Net基类库。这一句的作用就是告诉编译器去哪里寻找Console类以便调用。 接下来声明了一个类HelloWorld,这个类中有一个特殊的方法Main(),每个可执行文件都需要有一个入口点,在C#中,这个入口点就是Main()方法,此方法将在程序启动时被调用。在这个方法中,Console是在命名空间System下的一个类,它表示的是控制台。这里调用其静态方法WriteLine()。如同C++一样,静态方法允许我们直接作用于类而非实例对象。WriteLine()函数接受字符串类型的参数"Hello World !",并把它送入控制台显示。如前所述,C#没有自己的类库,它直接获取Microsoft.NET系统类库。在这里正是通过获取Microsoft.NET系统类库中的System.Console.WriteLine()来完成我们想要的控制台输出操作。现在使用记事本来编写这段代码,并将它的文件名保存为HelloWorld.cs,其中".cs"是C#源代码文件的扩展名。然后在配置好C#编译器的命令行环境里键入"csc HelloWorld.cs"编译文件。可以看到编译输出文件HelloWorld.exe。键入HelloWorld执行这个文件可得到下面的输出: Hello World ! 这就是第一个C#的程序,我们使用csc.exe来编译它,对于这个C#编译器,有如下说明: 1. 它是随.Net Framework SDK免费发布的,可以在DOS命令行被调用 2. 它的使用方法如下:   csc SourceFile.cs /out:TargetFile.exe   如果不使用输出参数指定目标文件名,则默认输出为源文件名 3. 一般情况下,它在系统文件夹(Windows或WinNT)下的Microsoft.NET\Framework\v1.0.3705文件夹内 4. 如果你安装了VS.Net,从Visual Studio.NET Tools项目组中可以激活Visual Studio.NET Command Prompt窗口,这是一个配置好C#编译器的命令行环境 5. 使用csc.exe编译后的C#程序并不是机器代码(尽管拥有.exe的后缀名)。如前所述,C#程序只是被编译成了MSIL代码。 C#编译器(csc.exe)编译后的文件并不是一个严格意义上的可执行文件(并不包含机器代码),而是一个PE(portable executable)格式的文件,虽然它同样拥有.exe的后缀名。在这个PE文件中也不仅仅只包含中间语言,在其中还包含有元数据(Metadata)和一个由编译器添加的目标平台的标准可执行文件头。 中间语言,确切地说,应该称为微软中间语言(Microsoft Intermediate Language,MSIL),是由微软定义的一种界于源代码与机器码之间的一种语言。在CLR中,它首先会由特定的语言编译器将其包装成exe格式的伪代码(P代码)。再由特定的编译器将其转换为本地代码执行。对于微软中间语言,一个形象的比喻是:如果CLR是操作系统的话,那么微软中间语言就是.Net平台上的ASM汇编语言。它比大多数 CPU 机器语言更为高级,比如它可以理解对象类型,并具有创建和初始化对象、调用关于对象的虚拟方法以及直接操作处理数组元素的指令。它甚至还具有发现和捕获异常情况用于错误处理的指令。 元数据(Metadata)和MSIL共同存在于编译好的程序文件之中,描述了此程序包含的类型的定义、各种类型的签名及其它一些数据,相当于以前的类型库(Type Library),同时也记载了此程序所引用到的其它外部类。元数据的主要作用是将与代码有关的更多的信息提供给CLR。基本上,元数据用于如下各项任务:用于表示CLR用途的信息,如定位和装载类、内存中这些类的实例、解决调用、翻译IL为原始码、加强安全并设置运行时上下文边界。 一个由C#语言写就的源码文件在CLR环境中执行的过程是这样的:首先由C#编译器编译成包含了中间语言和元数据的PE文件,当我们在系统中调用这个文件时,CLR会启动一个编译器再将这个PE文件包含的MSIL代码转换成为托管的本地代码。转换MSIL代码为本地码的这个编译器就叫做JIT编译器(Just In Time,JITer)。请注意它并不是前面我们用到的C#编译器。 现在让我们看看JIT编译器是如何工作的:当PE文件被调用时,JIE编译器将其分解为MSIL和元数据,这时候MSIL并不直接让.Net去调用本地的系统接口,而是指定.Net系统去编译连接那些需要的CLR DLL,编译出百分之百的本地代码。整个的过程如下: 当一个类型被装载时,装载器创建一个存根(stub),并使它与类型的每一个方法相连接。当一个方法第一次被调用时,存根把控制交给JITer。JITer把MSIL编译为本地代码,并且把存根指针指向缓冲本地代码。已经被JITer编译的方法随后就直接调用已经产生的本地代码,减少了JITer编译和执行代码的时间。可以看到,JITer并不会一次性的将所有的MSIL都编译为本地代码,而是在我们需要时才即时编译,也就是说,有些代码可能从来都没有被编译过。很明显这样做的好处是既保证了运行期的安全性,又不会损失太多的效率。 这就是一个C#程序执行时的步骤。整个过程是这样的: 1) 由C#编译器将源代码编译为中间语言 2) 装入托管代码,这包括解决内存中的名字、表层类(laying out classes ),并且创建JIT编译所必需的存根。通过执行经常性校验,包括加强一些访问规则,类装载器同样也增强了安全性 3) 用JITer将 IL转换成原始代码 4) 装入元数据、校验类型安全和方法的完整性 5) 垃圾收集(GC)和异常处理 6) 描绘和查错服务 7) 管理线程和上下文以及远程管理。 不必全部理解这些概念,在以后的学习中将会一一的体会到它们的精彩,现在你需要做的(如果你还没这么干过的话),是找到ildasm.exe这个文件(一般情况下,它会和csc.exe在同一文件夹中)。顾名思义,这是一个MSIL的反汇编程序(.Net Framework IL Disassembler),在命令行窗口下输入ildasm helloworld.exe /out=helloworld.il就会得到两个文件:helloworld.il和helloworld.res。前者包括了反编译出来的元数据和MSIL代码,后者则是提取的资源文件。用记事本打开helloworld.il文件,可以看到它定义并实现了一个继承自System.Object 的HelloWorld类及两个函数:Main()和.ctor()。其中.ctor()是HelloWorld类的构造函数。在这个文件中还包括元数据和其它有关的信息。如果你觉得这样不够直观的话,可以在命令行窗口键入ildasm helloworld.exe,这样就可以启动ILDASM 窗口并向我们展示出反编译后的helloworld.exe文件。 请仔细将这些代码看上几遍,现在理解全部这些内容并不重要,但是希望你也能看一下文件中的元数据,这其中包含所有 Runtime 和编译器需要的有关程序集及其模块、类型和成员(如方法)的信息。 行文至此,我想谈一下学习。如你所知,在我们所处的环境中,学习总意味着是一个痛苦的过程,学习一种新知识好像总是为了自己的某种需求,我并不认为这样有什么不对,但我总觉着,除了拿到高薪和受人尊敬外,学习还应该带给我们更多的快乐。有些知识我们现在也许用不着,比如前面谈到的一些内容,但是我们了解了,就是一件值得高兴的事。 智慧本身就是好的,有一天我们都会死去,追求智慧的道路还会有人在走着。死掉以后的事我看不到。但在我活着的时候,想到这件事,心里就高兴。 ——王小波 今天是2002年4月7号,再过三天就是王小波的忌日了,不知道有多少人还会记得这个日子,还会记得这个人。本文的最后,我向大家推荐小波的作品——每一个心智成熟的人都应该读一读小波的文字。在他的杂文随笔集《沉默的大多数》中有一句话谈到了他作为程序员的一面: “今晚不把这段C++调通,老子就不睡了!” >>>未完,待续...

16,554

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧