xhliu 的个人资料青蛙王子的工作空间照片日志列表 工具 帮助

日志


12月21日

设计模式,7种构造型模式举例

在遥远的过去,有这么一个与世无争的小村子,村里有一个村长(A)和很多的村民(Bs). 围绕着这个小村子,发生了无数的可歌可泣的故事.当然,和其他的故事一样,村子之外有一个可恶的皇帝(E).

 

1)       皇帝要让所有的村民交租子,他要经历下面的流程:

a)         他首先跑到村民b1那里收租子,村民b1的家里只有门,他就从门进入。

b)         他又跑到村民b2那里收租子,村民b2家里只有窗,没有门,他就从窗进入。

c)         村民b3家里门也没有,窗也没有,皇帝只好采用直升飞机空降的方式进入。

d)         。。。。

终于有一天,皇帝再也受不了了,他把村长叫过来,对他说:以后我收租子,只找你一个,从门进入,我收谁的你就跑腿。从此之后,可怜的村长就成了跑腿的人。皇帝很高兴,他把自己的创意称之为FACADE

2)       时光如梭。老村长不停的跑腿,终于累死了。于是村民b3当选为村长。这年,皇帝过来收租子,发现怎么都进步去村长的家里:村长家里没有门!皇帝想,“妈妈的,总不成每次都让我用直升飞机空降来收租子吧?”邪恶的皇帝又想了一个主意,他对村民b4说:“你在村长家外面造一个房子,把他的家全部包围起来,盖一个又宽又大的门,以后我找村长就找你了”皇帝很高兴,他又不用跑腿了,他把自己的想法称之为Adapter,而村长就成了Adaptee.

3)       时间就像小风一样嗖嗖的过着。村长不停的换,而邪恶的皇帝却始终活着,但是他已经厌倦了每次为新的村长找一个Adapter。他又开始思考了。他发现村里面的村们bx和自己一样的长寿。于是他改变了自己的策略,他让bx做这样的事情:准备好村长,准备好门。每次收租子的时候,他都只需要去bx那里问一下:“现在的村长是谁?”。然后就可以了。 皇帝又胜利了,他把自己的方法称之为Bridge

4)       有一天,邻国的女皇想到这个小村子里面参观。皇帝一看,“坏了,这些村民个个连衣服都买不起,光着屁股,我大国的威严何在阿?”于是,皇帝把自己的秘书d叫过来,对他说:“每个村民出来的时候,你给他们穿一个漂亮的衣服,别让他们给我丢脸!”最后,邻国的女皇看到的全是穿着漂亮衣服的村民。皇帝很高兴,于是他把自己的方法叫做Decorator

5)       村子越来越大,村民越来越多。终于有一天,村子分裂了,变成了两个村子。皇帝一看,每次收租子我都找两个村长,太麻烦了!于是邪恶的皇帝又有了点子:在村子之上设立乡政府,在乡政府之上设立县政府。。。 于是不管将来有多少的村民,自己都很方便管理,他把自己的方法叫做 Composite

6)       终于有一天,皇帝有了自己的王国,村门很多很多,管理起来太过于复杂。皇帝每天要处理每个村民的事情,忙的头昏脑涨的。于是,邪恶的皇帝又有点子了,他成立了一个特殊部门“东长”,然后又制定了惩罚规定,叫做“拘留,坐牢,流放,砍头”。每当有一个村民发生问题的时候,皇帝就问“东厂”:他的问题怎么办? 东厂说:坐牢。又有一个村民发生了问题,皇帝问东厂:怎么半?东厂说:他的问题以前的不行,我又发明了一种新的处理方法,叫做“凌迟”。皇帝很高兴,自己终于又可以轻轻松松的管理国家了。他把自己的方法称之为Flyweight.

7)       皇帝继续做着自己的美梦。他越来越依赖于自己的宠臣太监t了,不管有什么问题,他都问t,然后t去处理。他问t:我们有多少国民阿?t说,1000万。他问t说,我们有多少收入阿,t1000万。其实t已经大权独揽,自己腰包里面赚了无数的10000万了。T自己偷偷的大笑:哈哈,我就是传说中的Proxy!!

设计模式: Adapter

Adapter其实是一种封装.举例子如下:
 
我们有四种类
1) 苹果: public 水果
2) 梨: public 水果
3) 香蕉: public 水果
4) 玉米
而水果有一个接口,可以知道他的重量.玉米没有这样的借口.
 
class 水果
{
   virtual int Weight();
}
 
在程序中遇到这样的情况,最理想的是用一个for循环来遍历所有的水果,可以分别得到他们的重量,但是,居然有玉米!!一个玉米让我们没有办法用for循环,只能用if else语句.那有没有什么方法可以解决这个问题呢? 当然有,就是我们的adapter.
 
这里玉米就是adaptee, 我们可以生成一个叫做 "玉米果" 的adapter,有两种方法,如下:
 
1) class 玉米果: public 水果,private 玉米
{
   virtual int Weight();
}
2) class 玉米果: public 水果
{
private:
     玉米的实例.
 
public:
    virtual int Weight();
}
 
这两种方法都在程序上保证了玉米果是一个"水果",他已经不再保证他具有"玉米"的特征(私有继承和私有变量)
如果采用"class 玉米果: public 水果,public 玉米"的方法,那么就是一个双向适配器
 
可插入适配器: 可插入适配器的核心特征为,他不光可以为一个类做适配工作,还可以为很多类作适配工作. 比如上面的例子,我们又出现了 红薯,土豆 等等,如果我们的适配器可以满足这些操作,那么就称之为 可插入适配器.
 
可插入适配器需要寻找这些类的共同接口集合,或者使用proxy
12月20日

设计模式:5种创建模式举例

为了加强对这五种创建模式的理解,我就拿电脑生产做为例子。 一个电脑包含很多组件:CPU, Disk, Monitor, keyBoard, Mouse。
当然,首先我们有5种Factory: CPUFactory, DiskFactory, MonitorFactory, KeyBoardFactory, MouseFactory。这里采用的就是Factory模式,例如CPUFactory可以有Intel, AMD等等,DiskFactory可以有Maxto, Seaga等。这几个都是电脑组件的程产厂商,对于一个电脑的组成厂商,它需要声称这几个Factory的实例,以便于每次需要一个组建的时候就可以直接生成。于是一个全球的管理全部电脑组建的Abstract Factory就出现了。 人如其名,这个抽象工厂真的是抽象的,并没有这个组织。
 
class CPUFactory
{
public:
   virtual CPU* CreateCPU();
}
 
class IntelCPUFactory : public CPUFactory
{
public:
   virtual CPU* CreateCPU();
}
 
class AMDCPUFactory: public CPUFactory
{
public:
   virtual CPU* CreateCPU();
}
 
class MousePrototype
{
public:
   virtual Mouse* CreateMouse();
}
 
class SingletonAbstractComputerFactory
{
   virtual CPUFactory* CreateCPUFactory();
   virtual DiskFactory* CreateDiskFactory();
   ...
   virtual MousePrototype* CreateMouse();
}
 
显然,这个Abstract Factory只需要一个,因此它是singleton的。这样不管在世界的任何地方,我们制造一个 IntelCPUFactory,我都可以制造出来。
 
上面的Abstract里面CPU和Disk都是声称了一个Factory,例如可以生成IntelCPUFactory,生成MaxtoDiskFactory。而由于很多Mouse都是从一个原型里面做了一些修改,所以可以声明原型法。
 
有了上面的定义后,我们就可以在程序的任何地方,来得到一个CPU或者一个Disk,例如:我们在SingletonAbstractComputerFactory中只生产IntelCPU(这个可以写死在代码里面,也可以配置),如果需要生产其他新种类的CPU,只需要修改这个singleton类就可以了。
 
现在组建都有了,我们需要一台电脑,怎么办呢?我们可以让联想公司做这件事情,这就是builder
 
class Builder
{
public:
    virtual void SetCPU(CPU* cpu);
    virtual void SetDisk(Disk* disk);
    virtual void LinkToComputer();
}
 
class LegendBuilder : public builder
{
public:
    virtual void SetCPU(CPU* cpu);
    virtual void SetDisk(Disk* disk);
    virtual Computer* MakeComputer();
}
 
这里可以看出:builder和Abstract Factory的区别,可能他们的声明都是一样的,但是做的事情不一样。Abstract Factory侧重的是创建几个东西,而builder侧重的是把已经有的几个东西组成一个新的复杂的object。所以,intel是Factory,而联想是builder。
 

设计模式:Abstract Factory和Builder

如果说 Factory和Prototype是同一个层次的话,那么Abstract Factory和Builder就是更高一级的层次。
 
1 Abstact Factory
   在上面的Factory类型中,我们发现如果种类变了,我们还是要修改我们的代码: Factory = new 宝马工厂。 这样的代码可能出现在很多的地方,改起来并不是很方面。那么怎么办呢? 我们能不能把修改集中在一个地方?答案是可以的,那就是Abstract Factory。我们专门生成一个类来管理工厂,把 Factory = new 宝马工厂 这句话放到他的入口里面。
 
class AbstractFactory
{
protected:
     AbstractFactory():_instance(0){}
public:
    virtual Factory* CreateCarFactory()
    {
        if(0 == _instance)
        {
             _instance = new 宝马工厂。
        }
        return _instance;
    }
private:
    Factory* _instance;
}
上面的代码实现了一个简单的singleton的Abstract Factory。这样,如果下次用户需要一个新的工厂,那么可以从这个AbstractFactory里面派生一个新的类,或者修改代码等等。
 
这时候,有人要问了,这种操作我们直接用Factory也可以实现阿,直接把原来 宝马工厂 的实现修改不就行了么? 当然可以,但是Abstract Factory的存在价值是 他可以支持更复杂的创建。比如一个军工厂,他生产轿车,飞机,坦克等等。其中的轿车就是我们上面说的轿车,也有很多自己的。我们就可以为军工厂实现一个自己的Abstract Factory.
 
class AbstractFactory
{
 public:
    virtual CarFactory* CreateCarFactory();
    virtual TankFactory* CreateTankFactory();
    virtual PlaneFactory* CreatePlaneFactory();
}
 
可以看出,一个Abstract Factory的价值在于它可以创建更多的工厂类。当然,他也可以创建具体的实例,prototype类,等等,甚至可以创建一个新的子AbstractFactory。 所以Abstract Factory类似一个总的管理者,管理的是各个实例的工厂。正因为如此,一个程序里面的Abstract Factory往往是singleton的。
 
 
2. builder
builder 也是一个高层建筑,但是他和Abstract Factory侧重点不同,Abstract Factory侧重于创建东西的结果,而builder侧重的是创建东西的过程。
 
class CarBuilder
{
public:
  virtual void Setwheel();
  virtual void SetMoto();
  virtual void SetSeat();
 
   virtual Car* GetCar();
}
 
在调用的时候采用
 
Car* CreateCar(CarBuilder& cb)
{
   cb.SetWheel(轮子);
   cb.SetMoto(马达);
   cb.SetSeat(作为);
   return cb.GetCar();
}
 
上面的例子可以看出builder的特征。

设计模式:工厂和原型

1:工厂(Factory Method)
 
首先,工厂这个名字取得很好,就像前面说的,创建型模式的意义在于把生成一个变量从手工作坊(new,delete)的方式变化到工业化的模式,那么这里的工业化模式最典型的就是工厂(Factory Method)。工厂自己也是一个类,也会生成实例,工厂的功能就是为了创建另外一些变量。举例子,我们有奔驰车,宝马车,马拉车等等。现在我们要为他们生成变量,手工作坊和工业化的区别如下:
 
1)  手工作坊 
   MyCar = new 奔驰。
 
   显然,如果有一天,你需要了一个新的车,叫宝马, 就需要把程序里面所有的MyCar = new 奔驰换成 MyCar = new 宝马。这样实在太麻烦了。
 
2) Factory方式
   首先我们需要一个factory的实例  Factory = new 轿车工厂
那么我们需要奔驰车的时候就是用 MyCar = Factory.CreateCar()   //这里的Factory 是奔驰车的工厂
我们需要宝马的时候就用 MyCar = Factory.CreateCar()             //这里的Factory 是宝马的工厂
 
看,不许要修改那么多了吧?这个就是Factory模式的好处。
 
3) 缺点。
    可惜,Factory模式并不能一点都不修改,他需要修改一部分,就是Factory自己的创建
当从Factory = new 轿车工厂 创建一个工厂的时候,必须要指定是哪个工厂。比如下面的例子
 
class 轿车工厂
{
}
 
class 宝马轿车工厂:public 轿车工厂
{
}
 
class 奔驰轿车工厂:public 轿车工厂
{
}
 
那么,当你想从宝马车换到本车车的时候,就必须有下面的变迁:
Factory = new 宝马轿车工厂  ==> Factory = new 奔驰轿车工厂
 
 
2: 原型 (Prototype)
 
工厂模式还是有局限性的,比如轿车,我们需要的轿车可能会越来越多:奔驰,宝马,法拉利,A,B,C,D。。。。。可能有好几百种。采用工厂模式,我们必须给每一种车辆设计一个他的工厂,这个会生成好几百个类!!!!!!!
 
然而,我们其实并不需要声明这么多的类,因为好多工厂都是类似的。比如上面的几百个例子中,有几个这样的例子:宝马1型,宝马2型,宝马3型,宝马4型,宝马5型,宝马6型。虽然他们的差别很小,但是Factory模式必须为他们每一个生成一个类!显然,我们可以用下面的方式来生成几个类:宝马原形, 然后 宝马1型= 宝马原形(发动机1),宝马1型= 宝马原形(发动机2)。。。
 
这就是原型模式!
 
原型模式的存在价值就是减少 Factory模式的类的种类。
 
原型模式有以下几点注意事项:
1) 原型能大大减少类的数目,但是并不会把上面轿车几百种变成一种,所以我们需要一个原型管理器。用associative store的方式保存,可以注册,删除,引用一个原型。这种管理器也可以是一个扩展的singleton对象,这点就有点类似Abstract Factory了,但是功能不一样。
2) 克隆操作。也就是c++里面的拷贝构造函数。同一个一个原型实现一个新的实例,必须要注意把原型拷贝到新的实例里面的操作。
 

设计模式: singleton

singleton模式是5种创建型模式中最简单的一个了,一句话:  整个程序中只有一个实例. singleton还是有很多用处的,比如打星际争霸,一场游戏中只能有一个地图, 最多8个玩家. 这里的地图就是一个singleton,而玩家就应该是一个扩展的singleton。
 
其实,直接声明一个global static变量,也能保证全局只有一个实例,可是他的问题在于,自己声明了一个变量,然后过了两年,别人看到了自己的代码,要重新用它,已经忘记了原来的用途,这时候,10个8个变量都有可能了。
 
singleton模式的意义在于在代码上保证了他不能声明多个变量,如果声明了就会编译错误。这个市符合effective c++中的一个原则的:如果你在设计上就不考虑它,那就应该名令禁止他。
 
然而,singleton还是有很多问题的,比如在多线程的时候,在dll中,只有考虑了这些问题的singleton才是真正的singleton。

学习设计模式 第一天,第二天

根据老大的推荐,决定看设计模式这本书,看了之后发现果然是一本好书.
 
这两天看得主要是创造型模式,主要有5类: Singleton, Factory Method, Prototype, Abstract Factory, Builder
 
总的来说,这5种模式主要是为了创建变量的.举一个例子,我们要写一个游戏星际争霸. 里面有很多的东西,比如小兵,坦克,飞机,碉堡等等. 这些对象的创建,摧毁都应该有一个系统的方法. 如果到处new来delete去的,系统做大了就没法工作了.
 
总而言之, 创建型模式就是为了把创建变量这个神圣的事情 从手工作坊(单独的new) 提升到 工业化(5种模式) 的高度.
 
以上个人理解.
8月21日

strong code

经过这么长时间的training,发现把自己的代码编程solid code是非常必要的。而成为solid code的第一步,就是改变以前的种种毛病,真正让自己的代码毫无问题。写出solid code有几步是必要的。1)进行代码design。2)进行变量、函数名字设计。3)进行注释的编写。4)进行单元测试。5)进行buddy build。6)进行代码review。7)形成上述工作的适合自己的checklist。现在要一步一步的学习。
7月25日

学习c#第4天

31:c#中的windows编程中的控件
答:c#中的空间都是从Control类中派生出来,Control类中主要有消息路由等信息。而控件在窗口中布局的时候,通过代码控制和通过ToolsBox控制是完全等同的,只需要最后用this.Controls.Add()添加相应的控件就可以了。
 
32:c#中的自定义控件
答:c#中的自定义控件有3种。
     1) 从原来控件类派生出来的控件,如Button, TextBox等,他们可以直接使用,也可以改变了某些属性后使用,很方便。
     2) 直接从Control类派生出来的控件,通过填写一些必要的接口以后,就可以使用,使用方法不需要经过ToolsBox来拖动,直接添加就可以了。
     3) 多个控件的组合,从UserControl类派生出来的类。他生成一个控件集合:控件库。放在一个dll文件里面。在使用的时候,只需要在ToolBox中导入这个dll,控件就会出现在ToolsBox上,用户就可以使用了,方法和一般的控件差不多。
 
33:编写测试程序:俄罗斯方块1.0版,定义如下:

Smart blocks设计思想:

设计一个俄罗斯方块程序,用来练习c#。

 

1.0版,应该包含以下功能:

1)        标准的俄罗斯方块程序

2)        游戏的开始、结束、记分、时间、庆祝等功能。

 

以后版,应该包含以下功能:

1)        用户管理,积分榜

2)        变异方块、对战

3)        网络对战

4)        基于web程序等

5)        难度选择、针对层数等的扩展

 

1.0版包含的模块:

1)        包含一个方块的容器:BlocksContainer,具有以下功能

a)         可以选择背景,可以配置

b)        设置方块数目宽、高(默认10宽,25高)

c)        可以设置心跳(正常心跳、快速心跳)

d)        设置每个方块的宽高(宽=高,根据分辨率设置最好的)

e)         移动方块及方块组:左、又、下

f)         对方块组的变形

g)        删除方块组

h)        重置方块组

i)          重新生成一个方块组()

 

2)        方块组:BlocksGroup,具有以下功能

a)         旋转功能,给出旋转后的组

b)        移动功能,给出移动后的组

c)        显示功能,整体的显示可以和几个单个的显示不同

3)        方块:Blocks

a)         显示功能:形状、颜色等

b)        大小:高,宽(默认两个相等)

c)        擦除和显示

7月24日

学习c#第三天

27:一些基本的类库
答:功能强大的c#必须有一堆功能强大的类库支持,不然在处理问题的时候也会有心无力。显然c#不负众望,给用户提供了功能非常强大的一些类库。而支持文件操作的类库很完善,最游泳的两个是FileInfo类和DirectoryInfo类,他们都位于System.IO命名空间内部。处理这两个类的信息还有两个静态类:File和Directory。他们提供了文件的读写、创建、删除等功能,以及目录的读写、创建、删除等功能。
 
28:c#中的流 
答:System.IO.Stream类可以处理大多数的任务,例如从文本文件、二进制文件、其他变量还是从internet上读取文件,他都可以胜任。需要处理自己的特殊类型的,只需要从他派生出来一个类然后再做相应的处理就可以了。
 
29:Windows.Forms编程
答:虽然现在的程序越来越多的是基于web的程序,但是单击的窗口编程依然具有重要性。c#提供了一套专门为窗口编程的类库。一个窗口是从System.Windows.Forms.Form继承出来。与传统MFC窗口编程的最大区别是:这里的整个窗口布局和属性等都是在代码里面编写的,不需要象以前那样资源和代码分离。而c#也提供了绝大部分普通控件的类库,用事件来管理他们的消息,非常方便。
 
30:编写测试程序。
答:为了检验最近的学习成果,编了一个Calculator.他具有的功能有:加、减、乘、处、倒数、开方等。界面如下。
7月21日

学习c#第二天

15c#是如何进行变长参数声明的?

答: 1c#号称总结了javac++的优点,那么变长参数的函数声明必然就是需要支持的。

2c#采用了params关键字来支持变长参数声明,而参数被填到一个数组中,例如:

              public void func(params int[] arr)

3) 如果各个参数类型不一致的话,可以使用public void func(params object[] arr)来声明

 

16c#中的强制类型转换如何?

答:和c#里面的其他部分一样,c#里面的强制类型转换语法要求更为严格。

1)  必须包含public static implicit operator或者public static explicit operator四个关键字的声明,缺少一个就会报错。

2)  显示转换其实是可以堪称implicit转换的一个特例,能隐式转化的一定可以显示转换。建议对implicit转换具有以下特点:不改变类的任何属性、不丢失数据等

 

17c#枚举型的特点

答:1c#枚举型全部都是从System.Enum类继承过来的,具有System.Enum类的所有接口。

2c#枚举可以定义自己的类型,但是不能是浮点的,默认是int

3)枚举默认的ToString()是自己的名字,如果按照int型输出才是他的值。

 

18c#中的预处理

答:1c#中减少、简化了c++里面很多的预处理,例如#include2)现在最常用的是预编译#define #if #endif等。3)还可以调用编译指令#warning #error4)一个比较常用的,为了编程方便的指令 #region#endregion

 

19c#中的委托delegate

答:委托在这里感觉有很重要的作用,因为他和事件event概念是联系到一块儿了。这里的委托更像以前系统里面的callback函数,也更像c++里面的函数变量,其实就语法角度来讲,感觉可以把它认为是一种声明函数的typedef,但是使用更方便。

    public delegate void func(object a, object b);

生成实例的话用  func fc = new func(p.f); 其中的构造函数必须是已经声明好的函数(如果是非静态函数,则要生成相应类的实例)

 

20c#中的事件event

答:在一般的windows编程中,都有消息处理机制,然而这些必须是和操作系统相关的,语言本身不具备消息处理。而在c#中,由于实现了和系统的分离,那么语言本身具备消息处理功能就成为可能,这就是c# event功能。他是基于委托的,声明如下:

       public event func et;

1) 可以看出,他有点象声明了委托的一个实例,实际上event更像是对相应委托的一个管理器,他可以添加(+=)、删除(-=)一个委托,还可以响应委托(上面例子调用委托的方法为et(a,b),他会按顺序相应所有委托,但是这个调用只能在类内部使用)。在此基础上进行消息管理机制,将会非常的方便。

2) 由于一种事件只能相应自己的委托,那么要具有通用性,就必须有通用的格式,在.net框架中,定义了一个通用委托和事件:

       public delegate void common(object sender, EventArgs arg);

通过System.EventArgs类派生出来的类,可以用来传送消息内容。

 

21c#注释使用xml文件

答:1)为了更方便的生成文档,c#允许在注释的时候使用专用的 ‘///’来作为 xml文档的标记,这种注释一般用在类前面、函数前面、命名空间前面等,在编译器选项上做适当的设置,编译后就自动会把这些注释生成xml文档。

2)  现在用的人可能不多,因为在达到vs2005的时候,把xml=>web page这个选项去掉了。

 

22c#中使用命名空间using

答:大部分情况下,这里的命名空间和以前的c++是相同的,但是同样的功能更强大、更方便。在c#里面想使用另外一个程序集的时候,只需要两个简单的过程:a)add reference添加相应的dll或者lib等。b)使用using包含里面的内容。 简单的两步就可以调用里面的所有东西,而且可以跨语言。 一个小技巧:

    namespace One.Two.Three

    {

    }

       等价与

    namespace One

    {

        namespace Two

        {

            namespace Three

            {

            }

        }

    }

 

23c#中的Type

答:1c#是很强大的,所以他有System.Type类,再也不用象在c++里面那样为描述类型而犯愁了。

2)有三种方式可以得到一个对象的Type,编译时得到(typeof),运行时得到(obj.GetType()),通过字符串名字得到(Type.GetType(str))Type对象的内容非常丰富,基本上包含了类的所有信息。

3c#如何能够得到他的类型,这个原理还不清楚,不过肯定很有意思

To Be Continued …..

 

24c#中的动态生成对象,或者叫后期绑定

答:既然c#中有Type类,那么动态生成对象就变得很轻松。可以通过名字字符串、类实例等等来生成新的对象,一句话,只要你有Type那么你就有新的对象。而c#是用System.Activator.CreateInstance来完成动态生成的。

 

25c#中的数组、链表、集合等封装

答:1)非常方便,所有的封装都集中在System.Collections命名空间里面,比较重要的有QueueStackArrayListSortedListHashTable等几个类,这几个类的内容都是以object为类型的,因此可以放任何东西在里面。在System.Collections.Specialized里面有几个特定的类,可以很方便的使用,例如:StringCollection

2c#里面所有的数组都是从System.Array派生出来的,因此具有他的所有接口。而且可以跨语言。

3)可以通过foreach来访问数组里面的内容,有些不能访问的类如果具有Ienumerator接口的话,可以通过System.Collections.IEnumerator类来访问相应的内容

 

26c#中的多线程

答:c#中的线程非常的方便,在System.Threading命名空间中有各种类来实现,生成一个线程如下:

            Thread t1 = new Thread(new ThreadStart(委托));

            t1.Start();

这样生成一个新的线程,完成委托的内容。另外可以用suspend()resume()来挂起和唤醒一个线程。对于共享资源,需要用lock来锁定一个资源,如下:

            lock (typeof(Class1)) //这样锁定一个类的所有静态成员

            {

            }

 

            lock (obj) //这样锁定一个变量

            {

            }

            lock (this) //锁定当前实例

            {

            }

 

 

7月20日

学习c#第一天

刚刚接触一门语言,所以就把他拿起来和c++比较,还是真有不少相同的地方,很多都是从c++里面发展过来的。就第一天的经验来说,最明显的就是把c++里面的继承发展成为这里的“接口”和“继承”两个概念。而多态、重载的概念简直和c++里面一模一样。下面把自己的理解写下来,熟悉c#的博友多多指点阿。

 

1c#c++总体上有什么不同?

答:1c#是一种纯的面向对象语言,不存在全局变量和全局函数,就连Main函数也是类内部的函数,只不过使用了public static 修饰符而已。

2c#改良了c++里面的很多吃力不讨好的部分,例如采用了垃圾回收的概念、从而去除了指针,各种声明也更严格、例如重载必须要用override关键字、对变量必须要赋初值,还有干脆把string类型作为一个基本类型,异常的处理也更为强大、可以跨语言处理异常,发展了c++里面的继承概念、抛弃了多继承、把他分为继承和接口两个概念。

 

一句话,c#功能更强大,也会使程序员更懒,以前程序员可以用记事本来编辑c++程序,现在想用记事本编辑c#程序估计不现实了。

 

2c#的数据类型和c++有什么不同

答:1c#的数据类型分为数值型和引用型,数值型包括基本类型和struct声明的结构的实例,引用类型包括string类型和class声明的类的实例,不管是数值型还是引用型如果不初始化都回给出一个编译错误。

2)数值型的数据是在堆栈上的,和c++里面的数值型是一样的。但是这里的数值型的大小是和环境无关的,例如不管在什么样的机子上int都是32位的。

3)引用型数据非常类似于c++里面的指针,只是自动回收而已。

 

3c#数组和c++有什么不同?

答:c#里面一共有三种类型的数组,第一种就是直接用类似 int[] a = new int[5];这样声明的单维数组。第二种是直接用 int[,] a = new int[3,4];这样声明的多维数组。最后一种是 int[][] a = new int[3][];这样形势的散列表。另外,c#中的数组本身就是一个整体对象,他知道自己的大小,当越界访问的时候会抛出异常。

 

4:循环和c++有什么样的区别?

答:c#里面多了一种循环,foreach循环,这个循环里的变量使用的是引用型的,所以如果改变其内容的话就会编译报错。例如           

foreach (int i in c)

                                 i = 3;

就会给一个error CS1656: Cannot assign to 'i' because it is a 'foreach iteration variable'错误

 

5switch语句和c++有什么区别?

答:基本一样,但是这里的switch语句的语法更为严格,必须具有break语句,不然编译报错。另外多了一个功能,就是这里可以添加goto case ;语句,但是如果这个goto设置不当的话可能会造成死循环。

 

6c#的异常和c++有什么区别?

答:1) c#的异常处理是基于.net框架的,因此采用c#程序抛出的异常用其他的程序语言也可以处理,大大的增加了程序的扩展性。

2)抛出的异常必须是System.Exception类的一个派生,不能是随便的一个类型。

3) 后面的处理catch必须顺序正确,不然会编译错误。

4) 比c++多了一个finally关键字,如下:

            try

            {

                   正常代码

            }

            catch ()

            {

                   出错处理

            }

            finally

            {

                   不管正确还是错误都要处理的

            }

学习c#第一天

7c#structclass有什么区别:

答:struct更像一个对基本类型的封装,因此他生成的数据位于堆栈上面。另外struct不支持继承相关的东西、不支持虚函数、不能从接口继承。总而言之一句话,struct就是为了对基本类型封装,要想做其他事情,请用class

 

8c#setget

答:就我的理解,感觉使用setget有点类似 functionattribute 之间的一种属性,他是为了不破坏类的封装所采用的折衷方法。重要的是,使用它就可以实现接口和功能、数据的分离,例如在 interface中声明某个量的getset,然后在其派生类中实现数据已经相应的代表意义,这样即使数据结构发生了变化,也不会影响他的接口。

 

9c#的重载操作符

答:c#去掉了c++中很多吃力不讨好的操作符重载,只保留了最常用的,例如+,-,*,/ >> << == !=等不会有歧义的。另外对[]操作符采用了 public int this[int index]这样的形势来替代。另外,加强了限制,比如 == !=必须成对出现。最后,所有的操作符重载必须是static修饰的。

 

10c#的继承和c++有什么区别?

答:1c#只有单继承,如果要实现c++里面的多继承,就必须使用 继承和接口两个概念。

2)增加了限制,增加了关键字。例如对于virtual函数的重载就必须使用 override关键字,派生类对普通函数的重载必须使用new关键字,抽象类的声明必须使用abstract关键字,防止派生必须使用sealed关键字。

3)由于是单继承,所以在判断两个类关系时候就变得简单,增加了 asis两个关键字, c = A is B是判断A是否在B的继承链上,如果在c=true,否则c=falsed = A as B,那么如果A is B d 是把A强制转化为B的引用,否则d = null4)在两个类之间直接进行强制转换的时候,转化失败会抛出异常。

 

11c# object类的基本函数ToStringEqualsGetHashCodeFinalizeReferenceEquals

答:在c#中所有的类都是由System.Object类派生出来,即使用户在使用一个新类的时候没有显示声明,编译器也会自动加上。而object有一些基本函数,例如Equals函数、ToString函数、Finalize函数、GetHashCode函数、ReferenceEqual函数。这些函数是每个对象都会遇到的。

1Equals函数是判断两个类是否相等,往往重载这个函数和重载operator == 操作符是等同的(string类中就是这么干的)。但是如果判断两个对象内容是否相等,还是用Equals比较好,operator == 可以用来判断引用是否相等。

2finalize函数是用来给垃圾回收器调用的。

3ToString函数很常用,不多说了。

4GetHashCode函数。感觉c#的一个比较方便的地方在于他可以很快生成一个hash表,System.Collections.HashTable类可以生成一个hash表,但是如果让他正常使用,就必须重载Equals函数和GetHashCode函数。

5ReferenceEquals函数感觉更像给调试用的,因为这里没有办法调用显示的指针,所以就用这个来判断两个引用是否指向同样的空间。

 

12string类型的特点

  1)在c#中,为了方便使用,专门对string类型进行了封装,为了同时考虑方便性和效率,采用了两个类:stringSystem.Text.StringBuild

       2string类型本身是存储在堆上的,而且一个string对象一旦生成,就不可改变。如果使用 + sub等操作,那么就会在堆上生成一个新的string对象,因此效率比较低。

       3)为了加快速度,string类使用了intern概念,有一个专门管理string的内存池(例如刚声明的常量字符串),在用户重新声明另外一个string的时候,他会先检查内存池中有没有相同的string,如果有就会给他一个引用。如果一个string是在动态生成的,例如 b = a + “cde’中的b,那么内存池中就没有他的存在。这时可以显示的调用string c = String.Intern(b)来把b的内容驻留在内存池中(这里是拷贝,bc指向不同内存),以后再声明和b内容相同的string时候,就会直接指向c的引用(c在内存池中,b不在,因此指向c而不是b)。

       4string类型的operator==Equals函数是完全等价的

       5)可以看出,string类在运算的时候有经常的拷贝字符串,这在比较大的字符串时是效率很低的,因此提供了System.Text.StringBuilder类。这个类方法是:先给他分配一个Capacity空间,默认是16个字符,然后每次大的时候Capacity自动加倍,3264128…其他的操作参见具体的函数

 

13c#的接口interface是什么概念

答:1c#剔除了c++里面的多继承概念,把它分为接口和单继承两个方面,这样更有利于程序的扩展,编程也更方便。一个类不能从多个类继承,但是可以从多个接口继承。

    2)接口更像c++里面的纯虚类,只不过没有virtual等关键字,派生类也不用override关键字。

    3)编译器对接口的检查更严格,如果在派生类中没有处理相应的接口,就会编译报错,如果没有带public关键字也会报错,如果继续派生没有使用new关键字也会报错。

 

14c#的索引器是什么概念?

答:类似下面的这种声明:public double this[int index],其实就是c++里面的operator[]操作符重载,但是由于这里的操作符重载必须用static声明,所以就只好给[]弄了一个特例。另外要注意在索引越界的时候,抛出一个IndexOutOfRangeException异常。

 

7月19日

开始学习c#

引用一个高手的话:
 
write by cash(天下第七)
2001.12.20
版权所有,翻录不究

代序

C#(独白):很多年之后,我有个名字叫做C#,任何一种语言都可以叫C,只要它足够强大,我不会介意别人怎样看我,我只不过不想别的语言比我更强大。
C#(独白):我还以为这世界上有一种语言永远不会过时,因为它太完美。在我出道的时候,我认识一种语言,因为它出生的时候办公室的窗外有一棵橡树,所以很多年以后,它有个名字叫java。
C#(独白):近年流行网络,到处都有电子商务,有电子商务的地方一定需要技术,有技术就会用到我,我是C#,我的功能是为技术人员提供服务,使他们能更快的开发产品。
VB.NET(自言自语):看你的年纪也二十出头了,这二十几年来,总有些语言是你想学的,或是有些语言你一直都学不会,有些语言太难,或者你一直想搞懂它,但是你不行。哈,又或者你觉得不值。其实学一门语言,很容易。我有个伙伴,它很友善,而且最近很热门,只要你随便花点心思,它一定可以帮你成为一个牛人,你尽管考虑一下。其实学一种语言也不是很容易,不过为了生活,有时候你不得不费点劲。
Anders Hejlsberg(独白):离开Borland之后,我去了这个公司,开发了另一种语言。
Bill Gates(独白):2月14日,情人节,每年这个时候,都会发生一些事,很多人体会到快乐,有更多的人则会感到更加孤独。今年,我带来了一个新产品。
Cash:不久前,我遇上一个人,送给我一个Copy,他说那叫VS.NET,用了之后,可以叫你忘记所有以前用过的开发工具。我很奇怪,为什么会有这样的东东。他说人最大的烦恼,就是选择太多,如果只给你一条路,你就别无选择,只能走下去。你说这有多开心。这套软件本来是打算送给你的,看起来,我们要再Copy一份了。
Coder(独白):对于太新潮的东西,我向来很难接受,所以这套软件我一直没有装。可能这套软件真的很有效,从那天晚上开始,Cash开始忘记了一些东西。

Coder:你还记得Dephi吗?
Cash:我想不起来了。
Coder:你还记的php吗?
Cash:我也不记得了。
Coder:你为什么老看那个杯咖啡?
Cash:因为很眼熟。

Coder(独白):那天晚上他玩到很晚,第二天大清早就走了。我不知道他为什么要拿那套VS.NET给我,但我看得出他很兴奋,每次有新的语言发布,他都会变得很激动。
Coder(独白):一个月以后,Cash去了一个很远的地方,那是他上学的地方,Cash曾经在那里生活了一段时间,有一天他们毕了业,Cash就从来没有去过。

Cash:能不能再快一些?
java:我现在只能这么快。
Cash:我以前好像见过你?
java:何止见过,我曾经是你最好的朋友,但是现在已经不是了,你还在这儿干什么?
Cash:前不久,我遇见一个人,他送给我一套软件,叫做VS.NET,用了以后,不管以前用过什么语言也会忘了,我很奇怪,为什么会有这样的东西,我用了之后发觉真的很有效,不知你有没有兴趣试试?
java:你知道MS和SUN的分别吗?MS,越来越不要脸;SUN会越用越心寒。
Cash:我们还会再见面吗?
java:不会!