这个星期开始了.NET FRAMEWORK的学习,跟C#的基础学习有些不同,这5天的学习都是一些比较高级的应用,所以比基础知识难掌握一些,但是相应的,应用熟练后对自己的提升也是很大的。

第一天

 
   首先学了.NET FRAMEWORK的基础知识,.NET FRAMEWORK的基础是公共语言运行库,虽然公共语言运行库的功能很多,但是最基本的原则是代码管理,以运行库为目标的代码称为托管代码,托管代码拥有以下特性:1跨语言集成2跨语言异处理3增强的安全性版本4控制部署5支持简化的组件交互6模型调试和分析服务。而是否是托管代码直接影响将来是否能用反射这个类找出源代码。
 
.NET FRAMEWORK另一个重要组件是类库,利用类库可以方便的做出各种应用程序,是一个综合性的面向对象的可重用类型集合,而我现在对类库的理解还很粗浅,或者说接触的不够多,需要磨练。
 
之后又学到.NET FRAMEWORK垃圾回收机制,传统的语言如C++,需要自己指定内存大小,分配内存,自己分配的内存肯定会存在大小差异,多个对象的情况下就会产生很多碎片,是对系统资源的浪费。而C#做出了很大的优化,实例化的时候,首先由系统计算字段所需的空间,对于对象所需的空间,.NET FRAMEWORK用两部分来处理:1同步块索引2类型对象指针。系统用事先计算好的空间来分配物理内存,然后新对象指针指到下一个可用区域,这样就使得内存的利用率十分高,减少碎片的产生,而且在垃圾回收的时候好做处理,回收首先是——标记阶段,即从根标记遍历到的对象,之后是压缩阶段,释放没有遍历到的对象,同时把后面的对象都向前压缩,新对象指针也跟着压缩,指向下一个可用区域。
 
这里又不得不提到CLR的垃圾收集器中很重要的一个概念:代(Generation,代的目的是提高应用程序性能。托管堆中的对象分为3代,其中第0代对象的生存周期最短,第2代的生存周期越长。所以3代的预算容量分别为256K,2M10M。当第0代的预算容量满了的时候,垃圾收集器开始工作,释放不需要的对象,同时仍然需要的对象就放到第1代,当1代也满了的时候,1代仍然需要的对象就成为了第2代。这种处理极大的提高了性能。
 
基础概念差不多就这样,然后学习的第一个.NET FRAMEWORK的类是文件和流的类,directory filestream File没什么好说的,基本上就是对文本文件的操作。而directory类的说法就比较多了,之前做了个控制台的资源管理器,就得用到directory的各种类,将来无论C/S还是B/S都不会少了它。而stream,我觉得很重要。流是字节序列的抽象概念,例如文件、输入/输出设备、内部进程通信管道或者 TCP/IP 套接字。掌握好流的应用是十分重要的,而流又分为3个基本操作,读,写,查找。虽然重要,但是并不是理解性的东西,记住格式即可
第一天的东西基本就这么多,把.NET FRAMEWORK庞大的世界打开了一个门缝。
 
 

第二天

今天主要讲了两方面的内容:1多线程 2 网络编程
 
首先来说说多线程,在学C#的时候,老桂让做过一个钟表的程序,附加有秒表,闹钟的功能。这个程序就必须用到多线程的知识,不过那时候还没有学,做起来很吃力,现在来看的话就能轻松完成了。每个线程都维护异常处理程序、调度优先级和一组系统用于在调度该线程前保存线程上下文的结构。所以说线程都是单独的,线程是分配处理器时间的基本单元。在同一个时间片只能有一个线程运行,其他的都是挂起状态。所以CPU繁忙的情况下,线程优先级的设置就对线程的执行起到很大的作用,上课的例子是兔子赛跑,在CPU繁忙的情况下,优先级最高的线程第一个跑完。而在CPU空闲的状态,3个优先级几乎是同一时间完成的。
 
线程的定义过程如下:首先定义线程的threadstart,用来表示在线程中执行的方法,然后定义一个thread,需要的参数为threadstart,之后就可以thread.start()了。Abort为中止线程执行。Sleep使线程睡眠一段时间,方法的参数为睡眠的毫秒数。其中sleep的使用次数是挺多的。需要注意的一个方法是lock,用来阻止共享资源被多个线程同时操作而造成的错误,lock类似于对象锁,不够正牌的对象锁是monitorMonitor 通过向单个线程授予对象锁来控制对对象的访问。
 
小知识:lock所用的卖书的范例即是典型的消费者和生产者模式。生产几本,就只能卖几本。
 
接下来就讲到了TCP/IP协议。
 
总体来说,在.NET用到的底层网络方面的知识不多,只要会用套接字就可以了。1需要建立一个ipaddress,这个IP地址必须是本机地址,因为framework只提供自己电脑的端口监听,不允许***行为。2,建立一个监听tcplistener,参数为本机地址和端口号。3,因为TCP为安全连接,所以也需要建立客户端的对象tcpclient,用于获取监听到的client4,用网络流netstream获得客户端发来的流。发送或者接收都通过流的形式。不过发送的时候需要将信息转化为byte的数组。用byte方法。
 
后来讲了服务器一对多客户端,又分为长连接和短连接,长连接就需要每次new一个监听的时候都新建一个线程,短连接则不需要。Framework几乎封装了所有底层的东西,对网络完全不了解也可以使用套接字。至于之后讲的UDP,因为通讯不需要握手,实现起来也相对简单。
 
多线程是很重要的知识点,以后做项目的时候肯定是离不开的,网络这块,做B/S的话,基本上就用不到。但是也得掌握。
 
 
 
 
 

第三天

今天的知识点是正则表达式和泛型。
 
首先说正则表达式,正则十分简练,十分强大,以至于完全理解正则很难,能做到日常应用即可。。
 
泛型以前接触过list类,现在学的主要就是如何自定义泛型类
class Demo<T>
    {
        T t;
        public T T1
        {
            get { return t; }
            set { t = value; }
        }  
    }
这样子,一个简单的泛型类就建立起来了,T可以传进任意类型。一般情况下,创建泛型类的过程为:从一个现有的具体类开始,逐一将每个类型更改为类型参数,直至达到通用化和可用性的最佳平衡。
 
基本上泛型和正则就这样了。。
 
 

第四天

今天才是重头戏,主要的知识点有反射,特性,序列化。
 
先说反射,用framework的反射,就不得不说到.NET程序的运行过程。其实所有程序都是经过两次编译一次执行。源代码经过编译器的第一次编译,形成了IL元数据,在经过CLR JLT的第二次编译,才转化为机器识别的代码,最后代码被执行。
 
每个托管模块都包含元数据表。包括两种表:一是类型的表描述源代码中定义的类型和成员,另一种类型的表描述源代码引用的类型和成员。
 
知道了元数据之后,反过来看反射,反射是编程的读取与类型相关联的元数据的行为。通读取元数据,可以了解它是什么类型以及类型的成员。比如类中的属性,方法,事件等。通过这种方式,可以获得一个已经封装好的DLL或者EXE程序里面的代码。当然前提是这个可执行程序必须含有。NET可识别托管模块。根据MSDN的解释,这种反射并非是.NET的弊端,而是语言的特性,并且可以通过混淆器手动的使反射失败。混淆器则是反射的天敌,混淆过的代码即使反射出来,也是一堆混乱并且难以理解的代码。而在程序中,用反射类对混淆过的程序进行反射只会返回一条语句,说明该文件已混淆。
反射很强大,尤其是结合了特性,序列化之后,会有很厉害的应用。
现在再说特性,
属性以两种形式出现:
  1. 一种是在公共语言运行库 (CLR) 中定义的属性。
  2. 另一种是可以创建的用于向代码中添加附加信息的自定义属性。此信息可在以后以编程方式检索。
属性具有以下特点:
  1. 属性可向程序中添加元数据。元数据是嵌入程序中的信息,如编译器指令或数据描述。
  2. 程序可以使用反射检查自己的元数据。
  3. 通常使用属性与 COM 交互。
 
掌握了属性后,结合反射,功能就十分强大了,老桂的例子是用几个类,添加了属性后,结合反射做了个数据库语句的生成程序,很奇异。
 
最后再说说序列化。
可以将序列化定义为一个将对象状态存储到存储介质的过程。在这个过程中,对象的公共字段和私有字段以及类(包括含有该类的程序集)的名称,将转换成字节流,而字节流接着将写入数据流。随后对该对象进行反序列化时,将创建原始对象的准确克隆。
序列化的关键字在于:对象状态,转成字节流byte
第一次用的时候,把字段定义成静态的,结果发现序列化中找不到,仔细想了想,静态字段是属于类的,而不是属于可实例化的对象,所以序列化不到。这是个需要注意的地方。
序列化对象需要在对象前加上[Serializable],没有这个特性的对象不会被序列化。而微软自己封装好的类,想序列化怎么做呢?继承下来,加上[Serializable]就可以了。。当然父类不能序列化的对象在子类里定义成序列化的是会出问题的。这时候就得用到以下的构造函数和虚方法
 
public class Person
    {
        public bool sex;
    }
    [Serializable]
    public class Chinese : Person,ISerializable
    {
        public string complexion;
        public Chinese()
        { }
        public Chinese(SerializationInfo info, StreamingContext context)
        {
            sex = info.GetBoolean("sex");
            complexion = info.GetString("complexion");
        }
 
 
    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
  public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("sex", sex);
            info.AddValue("complexion", complexion);
        }
    }
 
 
大概的知识点就这么多,当然还遗漏了很多,慢慢在实际中体会吧