摘要:内存管理是一个非常重要的东西,一个好的程序员应该对内存模型和内存管理有一个好的认识。首先我们了解一下资源,资源分为两类,即托管资源和非托管资源。托管资源:托管堆内存非托管资源:文件句柄、数据库链接、本地内存等这里的托管与非托管即指的是我们常说的垃圾收集器,被垃圾收集器管理的资源叫托管资源,我们常说的内存管理即指的是托管资源的管理,而资源管理即指的是非托管资源的管理。下面我们谈谈.NET的内存管理在分配内存的过程中,当保留的内存区域全部被用光时,这时候GC启动,通过对象图,进行扫描,找到那些不可达的对象,这些对象即为垃圾对象,然后对内存区域进行压缩,使垃圾对象被覆盖掉(这里基于一个前提:托管堆上
阅读全文
摘要:内存模型也是学习编程语言一个很重要的方面,随着程序的执行,内存模型时时刻刻都在发生着变化。学习一门编程语言需要有“时间”和“空间”上的认识,对于C#语言来说,“时间认识“从大的方面来说就是需要区分编译时和运行时的概念,”空间认识“即对内存模型和内存模型的实时变化有一个很好的了解。下面我们通过一个例子来看看内存模型的实时变化。下面先给出代码。using System;class Point{ int x; int y; public Point(int x,int y) { this.x=x; this.y=y; ...
阅读全文
摘要:定义:所谓泛型,即通过参数化类型实现在同一份代码上操作多种类型的数据,泛型编程是一种范式的转化(在这里体现为类型的晚绑定),他利用参数化类型,将类型抽象化,从而实现代码的灵活复用,精简代码。泛型的好处: a.减少了对对象进行装箱和拆箱所导致的性能成本,提高了效率。 b.赋予了代码更强的类型安全。 c.实现了更为灵活的代码复用。注:1.NET参数化类型不是编译(JIT编译)时被实例化,而是运行时被实例化。 2.由微软在产品文档中提出建议,所有的泛型参数名称都以T开头,这是作为一种编码的通用规范。在定义泛型时,可以对客户端代码在实例化类时用于类型参数的类型施加一些限制,如果客户端代码尝试使用某..
阅读全文
摘要:在程序中,当我们需要动态的去加载程序集的时候(将对程序集的引用由编译时推移到运行时),反射是一种很好的选择。反射为.NET类型提供了高度的动态能力,包括:元数据的动态查询、绑定与执行、动态代码生成。常用的反射类型包含在System.Reflection和System.Reflection.Emit,反射包括程序集反射、类型反射、接口反射、类型成员反射。编译时加载程序集下面先从一个简单的例子说起,假如我们有一个Point类如下所示:using System;public class Point{ public int x; public int y; public voi...
阅读全文
摘要:首先我们谈谈委托,委托是一种类型安全的函数指针,它支持更加灵活的晚绑定机制,是.NET中事件的支持机制。但是委托不仅仅限于函数指针,如果所绑定的方法为实例方法,委托将可以维护其所依赖的对象的状态信息。在整个.NET机制里面,共有三大晚绑定机制:虚函数、委托、反射。所谓晚绑定,即一个晚的东西调用一个早的东西。晚绑定的设计理念很重要,很多关键的设计理念都是由晚绑定来支持的。如果没有晚绑定,只有早绑定,设计上做不出来什么好的东西,很多经典的设计模式都是以晚绑定为基础的。下面先了解一些委托对象的内存模型: 从本质上讲,委托是一个类,因此它就是一个引用类型,也因此它符合引用类型的内存结构模型,首先是在栈
阅读全文
摘要:线程优先级线程优先级的概念在很多技术框架下都有应用,.Net框架也不例外,.NET框架为程序员提供了方便的接口以供使用。系统会为每一个线程分配一个优先级别。.NET线程优先级,是指定一个线程的相对于其他线程的相对优先级,它规定了线程的执行顺序,对于在CLR中创建的线程,其优先级别默认为Normal,而在CLR之外创建的线程进入CLR时,将会保留其先前的优先级,可以通过访问线程的Priority属性来获取或设置线程的优先级别。 System.Threading命名空间中的ThreadPriority枚举定义了一组线程优先级的所有可能值,我这里按级别由高到低排列出来,具体的说明就不在这里解释。..
阅读全文
摘要:进程当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的。线程线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。多线程?多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。多线程的好处:可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。多线程的不利方面:线程也是程序,所以线
阅读全文
摘要:接口的标准化是一个产业强盛的标志。在C#中,面向接口的编程思想是.NET中重要的思想之一,接口是组建设计的灵魂,接口是一种引用类型,在.NET类型系统中,类和结构都可以实现接口,一个类可以实现多个接口,接口之间也可以实现多继承,即 一个接口可以有多个父接口。接口不是实体类型,不可以实例化,只是类型的行为合同规范。接口是面向组件设计与开发的灵魂。是现代软件开发的一个重要的设计手段。其实编程领域的很多思想都是从传统行业借鉴而来的,接口亦是如此。 首先我们来认识一下接口,public interface IPrint{ void Print(); void Process(); ...
阅读全文
摘要:1.对象的类型判断 任何一个对象它都具有双重类型的身份,即声明类型和实际类型,正因为对象有了双重的类型身份,因此也出现了类型兼容的概念。同时也因为对象的引用性质,也使它在判断相等的概念上具有多重意义(即存在引用相等和值相等)。 首先我们来看类型兼容,看一段代码:using System;class Fruit{}class Apple:Fruit{}class Test{ public static void Main() { Fruit f1=new Fruit(); Fruit f2=new Apple(); //类型通过虚函数表中GetType()函数获得 ...
阅读全文
摘要:概论首先我们需要了解一下.NET的编译机制,在.NET框架下,编译分为两个步骤完成,第一阶段编译和JIT编译,第一阶段的编译对于.NET平台上的不同语言会使用不同的编译器,C#语言所使用的当然是C#编译器,第二阶段编译是由JIT编译器完成的,关于编译机制的详细解释,这里不再赘述。 在第一阶段编译过程中,任何语言都会被编译成中间语言(IL)代码,程序集(Assembly)的文件负责封装中间语言。在经过C#编译器的编译以后,一般会形成两种形式的文件,.dll文件和.exe文件,如果被编译的类文件(.cs文件)文件中包含入口点函数(即Mian函数),那么这个类文件既可以编译成.dll文件(动态链接.
阅读全文
摘要:构造器:构造器一般用来进行状态的初始化,包括实例构造器和类构造器两种。构造器不支持继承,构造器存储在代码段中(和常量的存储地方一样)。实例构造器 实例构造器主要负责将类型的实例初始化到一个合理的状态。引用类型和值类型的实例构造器是有所区别的。如果我们没有定义实例构造器,那么编译器会为我们默认产生一个无参构造器。在调用构造函数前,变量被初始化为0或者null,所以没有被构造器改变的变量在实例创建后将保持0值。如果类没有显示定义构造器,编译器会自动生成一个无参构造器,调用基类的无参构造器。如果类的修饰符为static,编译器不会默认生成构造器;如果存在继承关系,派生类在使用基类的字段之前应该先..
阅读全文
摘要:摘要:今天我们漫谈C#中的垃圾回收机制,本文将从垃圾回收机制的原理讲起,希望对大家有所帮助。 GC的前世与今生 虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久。早在1958年,由鼎鼎大名的图林奖得主John McCarthy所实现的Lisp语言就已经提供了GC的功能,这是GC的第一次出现。Lisp的程序员认为内存管理太重要了,所以不能由程序员自己来管理。 但后来的日子里Lisp却没有成气候,采用内存手动管理的语言占据了上风,以C为代表。出于同样的理由,不同的人却又不同的看法,C程序员认为内存管理太重要了,所以不能由系统来管理,并且讥笑Lisp程序慢如乌龟的运行速度。...
阅读全文
摘要:SortedList :有序集合SortedList是和Array的混合。当使用Item索引器属性按照元素的键访问元素时,其行为类似于hashtable,当使用索引访问元素时,其行为类似于Array.Sortedlist在内部维护了两个数组以将数组存储在列表中,一个数组用于键,另一个用于相关联的值,每个元素都可以作为一个DictionaryEntry对象进行访问,因此SortedList一共有三种访问方式。SortedList列表的容量会根据其所拥有的元素个数进行调整,随着向SortedList中添加元素,容量通过重新分配,按需自动增加。索引顺序基于排序顺序,当添加元素时,元素按正确的排序顺序
阅读全文
摘要:定义:所谓泛型,即通过参数化类型实现在同一份代码上操作多种类型的数据,泛型编程是一种范式的转化(在这里体现为类型的晚绑定),他利用参数化类型,将类型抽象化,从而实现代码的灵活复用,精简代码。泛型的好处: a.减少了对对象进行装箱和拆箱所导致的性能成本,提高了效率。 b.赋予了代码更强的类型安全。 c.实现了更为灵活的代码复用。注:1.NET参数化类型不是编译(JIT编译)时被实例化,而是运行时被实例化。 2.由微软在产品文档中提出建议,所有的泛型参数名称都以T开头,这是作为一种编码的通用规范。在定义泛型时,可以对客户端代码在实例化类时用于类型参数的类型施加一些限制,如果客户端代码尝试使用某..
阅读全文
摘要:理解堆与栈对于理解.NET中的内存管理、垃圾回收、错误和异常、调试与日志有很大的帮助。垃圾回收的机制使程序员从复杂的内存管理中解脱出来,虽然绝大多数的C#程序并不需要程序员手动管理内存,但这并不代表程序员就无需了解分配的对象是如何被回收的,在一些特殊的场合仍需要程序员手动进行内存管理。在32位的处理器上,每个进程的虚拟内存为4GB,.NET会在这4GB的内存块中开辟出3块内存,分别作为栈、托管堆、和非托管堆堆(heap):堆是从下往上分配,所以已用的空间在自由空间下面,C#中所有引用类型的对象分配在托管堆上,托管堆在内存上是连续分配的,并且内存对象的释放受垃圾收集机制的管理,效率相对于栈来说要
阅读全文
摘要:先谈谈StringBuilder与String的区别System.String具备不可修改性,在程序中这样的特性容易产生性能问题。针对这一问题,.NET提供了StringBuilder类可以解决类似的问题String与StringBuilder均可以对字符串进行处理,它们具备不同的特点,下面将分别进行说明。String具备以下4个特点: 1.String为引用类型,在堆上分配内存。 2.String对象一旦生成,无法进行修改,如果进行修改操作(并非真正意义上的修改),则会在堆上产生新的对象,同时栈上的引用将指向新的对象。 3.String对象提供了大量字符串操作函数。 ...
阅读全文
摘要:首先我想了解一下什么是装箱和拆箱在类型系统中,任何值类型和引用类型都可以和object类型进行转化,装箱转化是指将一个值类型显式或者隐式的转化为一个object类型,或者是转化成一个被该值类型应用的接口类型,将一个值类型装箱,就创建了一个object实例,并且将这个值赋值给了object,object对象的数据位于堆中,在栈上有对该对象的引用,而被装箱的类型的值是被作为一个复制的文件赋给对象的,所谓拆箱,就是装箱操作的反操作,复制堆中的对象至栈中,并且返回其值。性能损失:相比于简单的赋值操作,装箱和拆箱需要进行大量的计算,对值类型进行装箱时,需要分配并构造一个全新的对象。为了解决装箱与拆箱带来
阅读全文
摘要:属性使用起来像字段,本质上是方法,属性是类成员重要的组成部分,访问属性和访问公共数据成员一样方便,但是属性的访问机制和公共数据成员的访问机制完全不同,它实际上是调用了内部相应的方法,那我们为什么不直接使用公共数据成员,而要使用属性了,首先我想说一下属性和字段的区别,C#是面向组件的编程,而字段是一个组件的实现细节,实现细节应该隐藏起来,,是不能暴露在组件外部的,应该定义为私有的,而属性是组件提供给外部的访问接口,必须公开。首先我想定义一个学生类,为了紧扣主题,该学生类暂时只包含学生的基本信息:年龄、姓名、学生人数(静态只读)。不用充分考虑,我们肯定会写出这样的一段代码:class Studen
阅读全文
摘要:我为了更好的理解C#中的委托,、泛型委托、匿名方法和Lambda表达式,我把它们的演变过程通过自己的理写了出来,各位高手要是看到有什么不妥的地方,还望指出。首先,我从一个C语言中很简单的一个问题开始,比较两个数的大小,并将最大的数以string 型输出首先来看比较常规的写法:public delegate string DelegateCompare(int Num1,int Num2); //定义委托 class Compare { public static string NumCompare(int Num1, int Num2) { return Num1 >...
阅读全文