RSS 2.0 Feed
.NET技术
摘要:二、了解CTS前的准备 1、 首先,说说堆(heap)与栈(stack,也叫堆栈),理解了最起码的堆栈概念,对于理解CTS绝对是必要的,而在最近给公司新员工培训时,发现他们根本不了解这块,所以我也觉得有必要单独再稍微说明下。对于heap和stack,简单的来讲,stack上分配的内存系统自动释放,heap上分配的内存,系统不释放,哪怕程序退出,那一块内存还是在那里。stack一般是静态分配内存,而heap上一般是动态分配内存。也正因为它们这种特性,在.NET里,对于托管堆(managed heap)采取了通过垃圾回收器(Garbage Collection,简称GC)进行自动回收内存操作。下面是stack和heap的对比说明,可以让你更好理解它们: l      Stack:堆栈本身就具有回收特性,每当程序执行到区块的结束点时,该区块的内存就自动被释放(Last-In-First-Out,简称LIFO,后进先出),这让我们没必要担心程序里使用了多少变量,因为变量在区块外立即自动被释放,保证了一直有足够内存空间。堆栈虽好,但可惜的是并不是所有信息都可以存储在堆栈中。例如我们经常使用的string类型变量,之所以把string变量存储在Heap中,是因为字符串的长度是可变的,无法直接在堆栈中分配内存空间,因为堆栈是静态分配内存的。 l      Heap:堆上的变量可以在任何地方被创建,在.NET里托管堆通过GC进行回收,至于回收方式,GC是通过标志方式进行回收的,即若有堆中的变量被标志为“待回收”,则未来GC会释放该内存空间。当然GC的回收远远不是这么简单,这里略过(有兴趣可以查看SDK文档或《深入理解.NET内存回收机制》一文)。 2、接着看下C#预定义类型: 运行时类型 C#预定义类型 描述 System.SByte sbyte 8位有符号整数 System.Byte byte 8位无符号整数 System.Int16 short 16位有符号整数 System.UInt16 ushort 16位无符号整数 System.Int32 int 32位有符号整数 System.UInt32 uint 32位无符号整数 System.Int64 long 64位有符号整数 System.UInt64 ulong 64位无符号整数 System.Char char 一个16位Unicode字符 System.Single float 单精度32位浮点数 System.Double double 双精度64位浮点数 System.Boolean bool 布尔值 true/false System.Decimal decimal 128位数据类型 System.Object object 根类 System.String string Unicode字符串 在.NET里,所有类型都是对象,而且都直接或间接继承自System.Object类。因此,例如我们声明并创建一个 int 类型时,实际创建了System.Int32的一个实例。例如: 1 public int i = 999; 2 public int j; 上面第1行代码,表示声明了一个 int 类型的变量 i,并赋值999。其实际是创建了 System.Int32 的一个实例,在堆栈Stack(为什么不是在heap堆上创建呢?这个后面会讲到是因为值类型和引用类型的区别)上分配一个内存空间存储了值999。 而第2行代码,只是声明了j,而没有进行赋值操作。在C#里,跟C++等不同的是,当你仅仅进行声明变量时,所发生的事就仅仅是“声明”,而没有进行实例的创建,也就没有进行内存空间的分配。例如,你声明了如下语句: 1 System.Web.UI.Page page; 上面仅仅就是个声明而已,没有真正创建page实例,也就是说没有在内存空间里实际进行内存的分配。而你要进行创建实例,并进行内存分配,有且仅只有通过 1 System.Web.UI.Page page = new System.Web.UI.Page(); 进行创建。也正因为这样,我们可以通过ILDASM看到上面声明的 j 实际是没有进行内存分配存储的。这也算是C#的一个新特征。这里额外也说了下。 下面是三个概念的理解: l      Managed Heap: 托管堆。是由CLR动态分配的连续的内存空间,在执行阶段由GC负责管理。整个进程共用一个托管堆。 l      Call Stack: 这是由CLR在执行时自动管理的内存空间,每个线程都有自己的Call Stack。每调用一次方法,Call Stack就会多一次记录,调用完毕该记录随即被丢弃。 l      Evaluation Stack:这是由CLR在执行时自动管理的内存空间,每个线程都有自己的Evaluation Stack。事实上,我们在CTS里常说的线程堆栈指的就是它。...[阅读全文]

posted @ | Feedback (8) |

摘要:     通用类型系统(Common Type System,以下简称CTS,有的地方也叫公共类型系统),算是个老话题了,但对于部分.NET程序员来说,可能还是需要这方面的知识。加上CTS是.NET里各种语言的基础,为了更好的进一步学习各种语言特性以及.NET Framework,也不得不了解CTS。我近期也在准备着一些.NET入门到提高学习资料,所以顺便整理下相关资料贴出来供大家参考(有可能的话,会按我整理的从入门到提高的系列一篇篇贴出来,不过就是要等待些时间),哪怕你对其中一点有心领神会的感觉,那也就够了。OK,转入正题。 一、CTS简介 我们都知道,编程语言发展至今已经有几百种,面对这么多的编程语言,经常有人陷入类似“生死抉择”的痛苦,但是有点体会的程序员总会说:“语言是互通的,只要你掌握了编程思想,遵循相应编程规范,就不用怕今天又出现了多少新语言”。我想这句话确实是有道理的。在这众多语言的背后,也隐藏着某种共性,不仅在语言本身,也在使用语言的方法上。就象大家常理解“程序=算法+数据结构”一样,我们也可以这样理解语言的共性,即“语言=语法+语义”。单纯字面上理解(不涉及编译等具体技术),语言实际上就是用各种事先定义好的关键字以一种特定组合方式起来的表现形式,用以定义数据以及描述对数据的操作。    了解了语言的概念,让我们思考下,是否存在一种东西(请原谅我用“东西”这个词)满足所有语言的共性?假如众多语言有了一种共性,是否可以进一步让众多语言之间实现互操作?再者,结合面向对象里的单根对象层次观点让每个对象最终都有相同的基类型,是否就又有了类型的统一功能?接着在统一类型基础上,又有了统一的调试方式、统一的体系框架、统一的开发手段等等呢?好了,再说下去都成完美神话了。上面的“东西”,实际上就是CTS。也正因为有了CTS,才有了.NET里“统一”的诸多特性,把CTS说成CLR(Common Language Runtime 通用语言运行库)的核心,编程人员必须掌握的特性一点也不为过。    下面引用MSDN里的CTS定义让大家有更清楚了解CTS,毕竟MSDN是权威: 通用类型系统定义了如何在运行库中声明、使用和管理类型,同时也是运行库支持跨语言集成的一个重要组成部分。通用类型系统执行以下功能: 建立一个支持跨语言集成、类型安全和高性能代码执行的框架。 提供一个支持完整实现多种编程语言的面向对象的模型。 定义各语言必须遵守的规则,有助于确保用不同语言编写的对象能够交互作用。 清楚了CTS的概念与优点后,我们更进一步来了解CTS。按照上面所讲的语言与CTS的关系,我们可以把CTS看成是.NET是所有语言的超集,也就是说各种符合CTS的语言,实际上都是CTS的一个子集。用数学的集合观点理解就是如下图:     从上图还可以看出在各种语言之间还有个交集——通用语言规范(Common Language Specification,简称CLS),这里也简单说下。我理解中,CTS是一套类型系统,而CLS则是事先定义好的一种规则,遵循这种规则编写的任何代码都可以实现跨语言的互操作性。事实上,通用语言基础结构(Common Language Infrastructure, 简称CLI,是CLR的子集。CLR与CLI的关系类似CTS与CLS的关系。)正是使用CLS来让各种不同的语言使用.Net框架各种资源。在实际应用上,对于CLS,如果我们项目里都只用一种语言,例如C#,那就没必要过度关心CLS。相对地,如果是多种语言结合开发,或者希望你开发的类库能让各种不同语言调用时,那么CLS绝对是你需要进一步了解的内容。...[阅读全文]

posted @ | Feedback (4) |

摘要:今天晚上刚好在整理C#讲义的装箱拆箱时,发现一个比较有趣的问题。为了说明装箱的例子,我使用了下面的例子: 1 2 3 4 5 6 7 8 9 static void Main() {     int i = 123;     object o = i;     i = 456;       Console.WriteLine("值类型i={0}", i);     Console.WriteLine("引用类型obj={0}", o); } 上面的例子很简单,但是当我问,这个例子到底发生了几次装箱操作,答对的可能就比较少了。答案是发生了两次装箱操作。其中第一次装箱操作是非常明显的,就发生在第4行。而第二次装箱操作,就发生在第7行上。为什么第7行又发生了一次装箱操作呢?下面是拷贝了ILDASM的代码,看了就知道了。   IL_0000:  ldc.i4.s   123   IL_0002:  stloc.0   IL_0003:  ldloc.0   IL_0004:  box       [mscorlib]System.Int32   IL_0009:  stloc.1   IL_000a:  ldc.i4     0x1c8   IL_000f:  stloc.0   IL_0010:  ldstr     bytearray (3C 50 7B 7C 8B 57 69 00 3D 00 7B 00......[阅读全文]

posted @ | Feedback (18) |

摘要:        我很少看到有关介绍ASP.NET页模板(Page Template,以下都称为Page Template)的中文资料,在外国站点上倒是看到过不少这方面资料,不知道是不是大家都不大习惯使用Page Template。我在开发ASP.NET WEB应用程序时,比较喜欢用它,而且效果也不错。今天翻译编著部分资料并整理了下,谈谈ASP.NET Page Templates吧。         当你正在开发的一个WEB站点的部分或所有页面具有一定共同元素,如Banner、版权声明、导航栏等;甚至是部分或所有页面都具有的功能,如身份验证Session判断、出错捕捉显示、数据操作及帮助提示功能等时,就会遇到这么一个问题:怎样让这些ASP.NET页面简单方便地拥有这些共同的元素和功能呢?        在以前ASP编程中,使用include包含文件来解决上面问题。Include文件虽然一定程度上解决了共享页面元素问题,但被包含文件与包含页面之间是紧耦合关系,这也就意味着你的页面必须包含并按一定顺序包含相应的头文件,否则程序将不能正常运行。同时,这种紧耦合关系,使得你在日后为了修改站点某一个显著界面或重要功能时,你将不得不修改每个头文件及每个ASP页面。现在,在ASP.NET中,利用ASP.NET新增的许多功能特性和面向对象我们完全可以找到更好的解决方法来解决这个问题。        因此,下面主要讨论的将是:ASP.NET有哪些途径可以解决页面元素或功能的共用问题?ASP.NET Page Template能带给我们什么效果? 一、 ASP.NET有哪些途径可以解决页面元素或功能的共用问题?1、 用户控件(User Controls)        在刚接触ASP.NET时,看过一两本台湾人的书,他们在其中介绍了有关Pagelet(他们称为“网页配件”的东西,感觉比较新鲜。后来才知道,Pagelet的真正名字叫User Control,我们称为用户控件。用户控件其实就是封装了HTML代码块及后部服务器端代码的一个小页面模块,以方便在许多不同的ASP.NET页面里复用它。该部分大家可能也都比较熟悉,就不多说了,更具体可以参考http://chs.gotdotnet.com/quickstart/aspplus/doc/webpagelets.aspx。用户控件仍然没有很好解决页面元素和功能共用的问题。比如,你封装了一个Header.ascx以让每个页面头保持一致,随之而来的是你的每个页面都必须拉放Header.ascx在一定位置;当你需要改变Header.ascx位置,将之放在每个页面底下时,你还必须把每个页面一个一个修改过去。2、 Page Template        在ASP.NET Web应用程序项目里,所有ASPX页都是继承自System.Web.UI.Page类。正因为如此,Page Template方案里,为了解决视图和功能共用问题,我们创建了一个继承自System.Web.UI.Page类的页面基类PageBase,并将Web应用程序中的所有ASPX页面继承自该页面基类PageBase。         从上图可以看出,在System.Web.UI.Page和ASPX页后部代码之间增加了一层PageBase,这将有助于我们把一些公用的视图或功能增加到PageBase中,以使所有页面都具有公用特性。下面为PageBase类代码: using System; using System.Web.UI; public class PageBase : System.Web.UI.Page {      private string _pageTitle;      public string PageTitle      {          get { return _pageTitle; }          set { _pageTitle = value; }      }      protected override void Render(HtmlTextWriter writer)      {          // 首先创建html及body节点          writer.Write(@"             <html>                 <head>                     <title>" + PageTitle + @"</title>                 </head>                 <body>");          // 其次允许基类呈现ASPX页面中的HTML代码及ASP.NET控件          base.Render( writer );          // 最后结束body和html节点          writer.Write(@"                 </body>             </html>");      } }         把一ASPX页WebForm1.aspx的HTML代码只留下<%@ Page ….. %>指令和<form>…</form>节点内的内容。如下: <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApplication3.WebForm1" %> <form id="Form1" method="post" runat="server">        This is a Test. </form>         在WebForm1.aspx.cs里: public......[阅读全文]

posted @ | Feedback (16) |

摘要:[注]:当时PetShop.NET 3.0出来时就整理的一份资料,之前硬盘被感染病毒遭破坏,后来恢复了点过来,近期有空稍微整理了下那些恢复过来的资料,发现有这么一份当时模仿PetShop.NET 3.0写的代码项目,于是稍微整理了下弄成资料放上来。时间久了,之间可能有理解偏差或比较欠缺的地方,还望大家指正。 一、项目前言 PetShop实现了什么业务功能,我想不用我多说。自从Sun弄了个PetStore作为Java经典范例后,似乎有点演变成为“Hello World”的趋势,只不过对PetShop来说,我想微软的意图跟Sun一样,都偏重架构与模式上的应用。PetShop.NET至今最新版本还是3.0版本,我想这个版本跟2.0差别比较大,一安装从解决方案里的11个项目就看出点苗头了。PetShop.NET 3.0通过编写相应的数据访问逻辑,然后简单修改配置文件web.config实现替换后台数据库系统的功能,在这个主题功能后面,它主要是用了.NET里的反射结合工厂模式来实现该功能。当时看完后,一时兴起,自己模仿它也弄了个只有一个表(2个字段)的很简单的模型。源代码可以从这里载[下载]。 二、项目结构 该解决方案名为DataChangeSample,一共含8个项目,每个项目都有它自己存在的一个主要目的,8个项目通过自身的主要作用互相结合联系在一起组合成了该解决方案的功能。项目结构图如下: IDAL:意思为 Interface Data Access Logic,数据访问逻辑接口。其下有AccessDAL、OracleDAL与SqlServerDAL实现了其接口,针对每种数据库系统编写的数据访问逻辑都要实现该接口。AccessDAL:专门针对Access小型数据库编写的数据访问逻辑,实现了IDAL接口。OracleDAL:专门针对Oracle编写的数据访问逻辑,实现了IDAL接口。SqlServerDAL:专门针对SQLServer编写的数据访问逻辑,实现了IDAL接口。DALFactory:数据访问逻辑工厂,由该工厂负责根据配置文件动态创建系统所需的数据访问逻辑对象。BizEntity:业务实体,实质为数据库表的抽象类。BizRule:业务规则。Web:表现层。因为只为演示,只提供一个增加操作。 三、组件图与工厂模式图: 四、项目安装说明 项目解压缩到根目录后,设置Web目录为Web共享即可。将Web.config文件里相应参数配置下,修改节点的value值为数据访问逻辑的程序集名为你当前所要的数据库访问逻辑程序集名,运行即可。 五、总结 整体感觉,整个结构还是挺清晰的。有一点严重不足的是针对每种数据库都要重新编写访问逻辑与访问帮助类。后来看了孙亚民先生的文章后有点启发,能不能把这些信息都通过XML文件保存,然后通过类似他的WebSharp中间件进行开发,会不会更加简单?这点我没有实现,不过我想应该是可以的吧。不知道下个版本的PetShop又要给我们带来什么样的架构和模式参考呢?...[阅读全文]

posted @ | Feedback (17) |