网络小鼠的博客

做人的态度决定程序员的生涯

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

只读字段只能在构造器内被赋值.

值类型不能定义无参构造器,但可以定义无参类型构造器...

访问限定修饰符:public private protect internal  protectinternal
字段预定义特性:static readonly
  调用类型构造器:类型构造器一旦被执行,它在整个应用程序域的生命周期内都不会再次被调用.因为是clr在负责调用类型构造器,所以我们应该避免编写需要以特殊顺序调用构造器的代码.
类型构造器中的代码只能访问类型的静态字段的讲法/

C#不允许我们已装箱值类型中的字段,但我们可以利用接口来欺骗C#使其改变已装箱值类型中的字段,

对于值类型实例的参数来说,传递给方法的将是值类型实例的一个拷贝,这意味着方法会得到一份属于它自己的值类型实例的,而调用该方法的代码中的实例不会受到任何影响.

如果一个方法的参数被标识为Out,那么调用代码在调用该方法之前可以不初始化该参数,并且被调用方法不能直接读取参数值,它必须在返回之前为该参数赋值.如果一个方法的参数被标识为ref,那么调用代码在调用该方法之前必须先初始化该参数.


1.定义一个类型用于保存所有需要发送给事件通知接受者的附加信息
2:定义一个委托类型,用于指定事件触发时被调用的方法原型
条播类型的名称应该以EventHandler结束.另外,回调方法的原型应该有一个void返回值,并用接受两个参数,第一个参数为Object类型,其指向发送通知的对象,第二个参数为一个继承自EventArgs的类型,其中包含所有通知接受者需要的附加信息.如果我们定义的事件没有需要传递给事件接受者的附加信息,我们便不必定义新的条播类型.直接使用FCL中的System.EventHandler,并将EventArgs.Empty传递给第二个参数即可,EventHandler的原型如下:
public delegate void EventHandler(Object sender,EventArgs e);
3.定义一个事件成员
其含义为所有事件通知的接受者都必须提供一个原型和委托类型相匹配的回调方法.
4定义一个受保护的虚方法,负责通知事件的登记对象
5定义一个方法将输入转化为期望的事件.


任何人都可以使用定制特性来定义一些信息,并将这些信息应用于几乎所有的元数据表项上,然后在运行时通过井底这些可扩展的元数据信息来动态地改变代码的执行方式.

System.FlagsAttribute特性允许我们将一个枚举类型看作一组位标记,System.SerializableAttribute特性允许一个类型的字段被序列化和反序列化(典型地用于方法参数和返回值的远程传送),几个安全相关的特性可以确保方法在试图进行某种特殊访问的时候具有要求的特权级别,许多互操作相关的特性可以帮助托管代码调用非托管代码.一个特性仅仅是一个类型的实例.定制特性的类型必须直接或间接继承自System.Attribute.

[assemblu:MyAttribute(1)]---应用于程序集上
[module:MyAttribute(2)]---应用于模块上
[type:MyAttribute(3)]---应用于类型上
[property:MyAttribute(4)]--应用于属性上
[field:MyAttribute(6)]--应用于字段上
[return:MyAttribute(7)]--应用于返回值上
[method:MyAttribute(8)]--应用于方法上
[param:MyAttribute(9)]--应用于参数上

查询是否应用 了特性,可以用System.Attribute提供的三个静态方法
IsDefined---如果至少有一个指定的Attribute的派生类型应用在目标元素上,该方法就会返回true.
该方法执行速度比较快, 因为它不需要构造(反序列化)任何特性类型的实例.
GetCustomAttributes该方法返回一个数组,其中的元素是指定的,应用在目标元素上的特性实例.每个实例都会用编译期间指定的参数,字段和属性来构造(反序列化).如果目标元素上没有应用指定的特性实例,方法将返回一个空数组.该方法通常用于那些将AllowMultiple设为true的特性
GetCustomAttribute 该方法返回一个指定的应用在目标元素上的特性实例.返回的实例使用编译期间指定的参数字段和属性来构造(反序列化)如果目标元素上没有应用指定的特性实例,方法将返回一个null如果目标元素上应用 了多个指定的特性实例,方法将抛出一个System.Reflection.AmbiguousMatchException异常.该方法通常用于那些将AllowMultiple设为false的特性.

System.SerializableAttribute类型,因为Serializable特性很常用,所以编译器会将它以一个位的形式编译到元数据中,而不必将Serializable特性实例的所有元数据都编译进去,这就是我们称这些特性为伪定制我的缘故:它们看起来和通常的特性很象,并且它们在源代码中的应用方式也和通常的特性一样,但是它们是以一种高度的形式(一个位)来存储的.


委托的技术来提供回调函数机制.委托可以确保回调方法是类型安全的.并且同时支持调用静态方法和实例方法.

public boid virtual Invoke(Object sender,EnventArgs args)

注意所有的委托都城有一个构造器,并且该构造器接受两个参数:一个对象引用和一个指向回调方法的整数.

反射对于开发人员来说是一个非常强大的工具,反射鸡毛我们构建可动态扩展的应用程序.例如,任何开发人员都可以开发一个类型,并将其打包到一个程序集中.如果该类型遵循规则,

 

 


AssemblyLoad 该事件在每次CLR将一个程序集加载到应用程序域中时被触发。事件处理器接受一个标识被加载程序集的System.Reflection.Assembly对象

DomainUnload 该事件在应用程序域卸载之前被触了。如果包含应用程序域的进程发生中断,该事件将不会被触发

ProcessExit 该事件在进程中断之前被触发。该事件只会为的应用程序域触发,

在处理Asp.Net web窗体时,一般在用户请求页面时,预编译站点,此时会发生几个事件:
1。asp.net处理器执行页面,确定必须创建什么,以实例化页面对象模型。
2.动态创建一个基类,包括页面上的控件成员和这些控件的事件处理程序(例如按钮单击事件)
3.包含在.aspx页面中的其它代码,以及页面的其它代码文件,与这个基类合并,构成完整的对象模型,所以需要在后台代码文件中创建一个部分类
4编译所有的代码,并高速缓存起来,以备处理以后的请求。
5生成HTML,返回给用户


主题必须在Page_PreInit()事件处理程序中应用,不能在所有页面使用的master页面中访问它,所以,如果要把选中的主题应用于所有的页面,有两个选项:
1.在所有要应用主题的页面中,重写Page_PreInit()事件处理程序
2为所有要应用主题的页面提供一个公共基类,再重写这个基类中的page_PreInit()事件处理程序


Web服务是利用SOAP(简单对象访问协议,Simple Object Access Protocol)在Http上执行远程方法调用的一种新方法。SOAP技术基于XML的标准,它详细描述了怎样在HTTP上以可重复的方式进行方法调用。

WSDL(Web Service Description Language,Web服务描述语言)来完整地描述Web服务,还可以在远行期间动态地查找Web服务。


 .Net Remoting 可以用于任何另一个应用程序域中的对象。不论两个对象是处于一个进程中,还是处于不同的进程中,甚至处于不同的系统中,都可以使用.net Remoting


下面列出了.net Remoting 体系结构的主要元素:
1 远程对象:远程对象是运行在服务器上的对象。客户机不能直接调用远程对象上的方法,而要使用代理。使用.net,很容易把远程对象和本地区分开:即每一个从MarshalByRefObject派生出来的类从来都不会离开它的应用程序域。客户可以通过代理对象调用远程对象的方法。
2.信道:信道用于客户机和服务器之间的通信。信道包括客户机的信道部分和器的信道部分。.net frameowrk 2.0 提供了三种信道类型,它们分别通过tcp .http .和ipc 进行通信。此外,还可以创建定制的信道。使用不同的通信。
3.消息:消息被发送到信道中,消息是为客户机和服务器之间的通信创建的。消息包含远程对象的信息,被调用方法的名称心腹所有的参数
4.格式标识符:格式标识符。使用Soap格式标识符,可以与不是基于。net framework 的web 服务通信。二进制格式标识符速度更快,可以有效地用在企业网环境中。当然,也可以创建定制的格式标识符。
5格式标识符提供程序:格式标识符提供程序用于把格式标识符与信道联系起来。在创建信道时,可以指定要使用的格式标识符提供程序,格式标识符提供程序则定义把数据传输到信道中时所使用的格式标识符

 

 

 


.net remoting 可以直接通过网络调用方法。远程对象必须继承自marshalbyrefobject.
在服务器应用程序中,要加载配置文件,只需要一个方法,就可以设置和运行信道和远程对象。在客户机中,我们载入配置文件并用使用运算符new 来实例化远程对象
即使不使用配置文件,也可以使用.net remoting 。在服务器上,只需创建信道和注册远程对象:而在客户机上,只需创建信道和使用远程对象。
.net remoting 体系结构也是非常灵活的,并可以扩展。这项技术的所有部分,如信道代理,格式标识符。消息接收器等都是可插入的,并可以用定制的实现方式来替代。
使用http tcp 和ipc 信道可以通过网络进行通信,使用soap和二进制格式标识符可以在发送参数前对其进行格式化。


message queuing 这个服务的主要功能如下:
1.消息可以在断开连接的环境下发送。不需要同时运行发送和接收应用程序。
2使用快递模式,消息可以非常快地发送。在快递模式下,消息存储在内存中。
3.对于恢复机制,消息可以使用有保证的将会方式发送。可恢复的消息存储在文件中。在服务器重时发送它们。
4.消息队列用访问控制表来保护,确定了哪些用户可以发送或接收队列中的消息。消息还可以加密,避免网络嗅探器读取其中的数据
5消息在发送时可以指定优先级,更快地处理高优先级的项。
6message queuing 3.0支持多播消息的发送
7 在事务消息队列中,消息可以参与dtc 事务


抽象类(abstract class)为一组概念上相似的类定义方法和公共属性。抽象类绝对不能被实例化。
属性(attribute)与一个对象相关联的数据(也被称为数据成员)
类(class) 对象的蓝图--为该类型的对象定义方法和数据
构造函数(constructor) 在对象被创建时得到调用的特殊方法
封装(encapsulation)任何形式的隐藏。对象对它们的数据进行封装。抽象类对它们派生出的胚体类进行封装
派生类(derived class)特殊化于一个超类的类。追念超类所有的属性和方法,但还可以包含另外的属性或不同的方法实现
析构函数(destructor)在对象被销毁时得到调用的特殊方法
功能分解(functional decomposition)一种分析方法,将问题分解成越来越小的函数
继承(inheritance) 一种类特殊化的方式 ,用于联系派生类和它们的抽象类
实例(instance)一个类的一个特定的对象
实例化( instantiation) 创建某个类的实例的过程
成员(member)类的数据和方法
方法(method)与对象相关联的函数
对象(object)负有责任的一个实体。一个特定的。自包含的容器,其中包含数据和操作这些数据的方法。一个对象的数据对于其它的对象是隐藏的。
多态(polymorphism)相关的对象按照各自类型来实现方法的能力

UmL

在分析阶段 
1 用例图, 用例图包括实体与系统(即用户与其它的系统)之间的交互,以及我需要实现的功能点
2 活动图,活动图关注问题领域(人和其它代理程序工作的实际空间,程序的目标领域)的工作流,而不关心程序的逻辑流。
观察对象的交互
1交互图,交互图表现出特定对象之间怎样互相交互。因为它们处理的是特定的情况而不是普高的情况,所以在需求检查和设计检查中都能帮上忙。最常见的一种交互图是顺序图
在设计阶段
1类图,类图详细描述类之间的关联
鸡窝一个对象在不同状态下的不同行为
1状态图,状态图详细描述可能处于的不同状态和状态之间的转换
在配置阶段
1配置图,配置图表现出不同的模块怎样配置。在本书中我也不会使用这种图

 

泛型的一个主要优点是性能。
ICollection<T>
方法和属性:
Add() Clear() Contains() CopyTo() Remove()
Count IsReadOnly
说明:
ICollection<T>接口由集合类实现。这个接口的方法可以用于在集合中添加和删除元素
泛型接口ICollection<T>继承于非泛型接口IEnumerable.通过ICollection<T>
可以把实现ICollection<T>的对象传送给需要将IEnumerable对象作为参数的方法
IList<T>
方法和属性:
Insert RemoveAt() IndexOf()
Item
说明:
接口IList<T>允许使用索引符访问集合,还可以在集合的任意位置插入或删除元素
与ICollection<T>类似,接口IList<T>也继承于IEnumerable
IEnumerable<T>
方法和属性:
GetEnumerator()
说明:
如果对集合使用了foreach语句,就需要IEnumerable<T>接口。这个接口定义 了GetEnumerator()方法,该方法返回一个实现了IEnumerator<T>的枚举
泛型接口IEnumerable<T>继承于非泛型接口IEnumerable
IEnumerator<T>
方法和属性:
Current
说明:
foreach语句使用实现了IEnumerator<T>的枚举访问集合中的所有元素
接口IEnumerator和IDisposable. IEnumerator接口定义了MoveNext()和Reset()方法IEnumerator<T>定义了Current属性的类型安全版本
IDictionary<TKey,TValue>
方法和属性:
Add() ContainsKey() Remove() TryGetValue()
Item keys Values
说明:
IDictionary<K,V>接口由元素有一个键和一个值的集合实现
IComparer<T>
方法和属性:
Compare()
说明:
IComparer<T>接口使用Compare()方法给集合中的元素排序
IEqualityComparer<T>
方法和属性:
Equals() GetHashCode()
说明:
IEqualityComparer<T>是比较对象的第二个接口,使用这个接口,对象可以进行比较,GetHashCode()方法应为每个对象返回唯一的值,如果对象,Equals()方法就返回true,否则返回false


泛型集合列表
List<T>
实现的接口:
IList<T> ICollection<T> IEnumerable<T>
说明:
List<T> 类一般用于替代ArrayList类.与ArrayList类相似,List<T>类也可以动态增大和减少其容量,除了实现了3个接口之外,这个类还支持其它功能,例如排序,使集合中的元素逆序。

Dictionary<TKey,TValue>
实现的接口:
IDictionary<TKey,TValue> ICollection<KeyValuePair<TKey,TValue>> Enumerable<KeyValuePair<TKey,TValue>  ISerializalbe IDeserializationCallback
说明:
Dictionary<TKey,TValue>是存储键和值对的集合类


SortedList<TKey,TValue>
实现的接口:
IDiction<TKey,TValue> ICollection<KeyValuePair<TKey,TValue>> IEnumerable<KeyValuePair<TKey,TValue>>
说明:
SortedList<TKey,TValue>类似于Dictionary<TKey,TValue>,但这个集合按照键来排序

LinkedList<T>
实现的接口:
ICollection<T> IEnumerabel<T> Iserializable IDeserializationCallback
说明:
LinkedList<T> 是双向链表,在双向链表中,一个元素引用它后面的前面的元素

Queue<T>
实现的接口:
ICollection<T> IEnumerable<T>
说明:
Queue<T> 是一个先进先出集合,队列中先添加的元素会被先读取,这类似于打印队列:最早的打印任务会最先执行 Enque()方法能在队列的发问添加一个对象:Deque()方法刚返回队列开关的对象,并删除该对象。 Peek()方法可以从队列中读取第一个对象,但不删除它

Stack<T>
实现的接口:
ICollection<T> IEnumerable<T>
说明:
Stack<T>是一个先进后出集合,堆栈中最后添加的元素会被最先读取,Stack<T> 提供了Push()和Pop()方法,Push()方法可以把一个对象添加到堆栈的尾部,Pop()方法则计取堆栈尾部的对象,并删除它Peek()方法读取堆栈尾部的对象但不删除它


.NET Framework提供了一些泛型集合基类,它们可用于创建定制的泛型集合类
类在System.Collection.ObjectModel命名空间中
Collection<T>
实现的接口:
IList<T> ICollection<T> IEnumerable<T> 
说明:
Collection<T> 类可用作定制集合烦扰基类,它实现了IList<T> ICollection<T> 和IEnumerable<T>接口。在后台上这个类使用List<T>类,但它没有提供List<T>的方法。所以对于定制的集合类,可以提供适合具体情况的方法。在定制的集合类中可以使用受保护的Items属性访问底层的List<T>对象
ReadOnlyCollection<T>
实现的接口:
IList<T> ICollection<T> IEnumerable<T>
说明:
ReadOnlyCollection<T>是Collection<T>类的只读版本,接口中允许添加和删除元素的方法都要实现,否则会抛出NotSupportedException异常
给构造函数传送实现IList<T>接口的任意集合,就可以创建这个类的对象
KeyEdCollection<TKey,TItem>
实现的接口:
IList<TItem> ICollection<TItem> IEnumerable<TItem>
说明:
KeyedCollection<TKey,TItem>的一个抽象基类,可以用于有键和值的定制集合类。这个类继承于Collection<TItem>

 

 

 


“委托”,delegate,其实我觉得翻译成“代表”还好一点,它“代表”一个样子跟他差不多的方法。例如有以下方法:

private int DoSomething(string s) {...}

和以下委托(还是入乡随俗吧,我也叫委托好了):

public delegate int DoThingsDelegate(string s);

那么,因为样子差不多(术语叫“特征”(signature)相同——参数列表和返回值一样),这个委托就可以“代表”上面的方法。具体的“代表”的方法是:

private DoThingsDelegate varDoThingsDelegate; // 定义委托变量
varDoThingsDelegate = new DoThingsDelegate(DoSomething) // 将方法与委托连接起来
int returnValue = varDoThingsDelegate("hello!"); // 使用委托调用被代表的方法

以上三步缺一不可,但是第二步通常都不是我们自己做的——如果我们自己已经知道了方法名字,为什么不直接调用方法呢?我们通常都是1)定义委托,2)定义委托变量,3)让别人对委托变量赋值,4)把委托变量看成是个方法来调用。

这就推断出委托的使用场合:当我们要调用某个方法,但是我们只知道这个方法该长什么样子而不知道具体从哪里获得的时候,就是使用委托的时候。

.NET 里,有两个地方最常使用委托,首先就是事件,不过这个等下再说,然后就是异步调用方法。异步调用方法,简而言之,就是叫一个对象“开始”一项工作,但不需要立刻返回结果,我也不等待结果,继续我自己的工作,到这个对象“完成”,可以返回结果的时候再“告诉我”。整个故事的难点就是“告诉我”——这个对象怎么才能知道该怎么告诉我?为此,我在叫它“开始”工作的时候,顺便把我的一个方法包装成委托,告诉它“做完了之后,用这个方法告诉我”。这样,工作对象就不需要知道我是谁/什么,完成工作之后尽管调用委托就行了。

事件摆在异步之后说,是因为事件是一种特殊的委托——可以“代表”多个同特征方法的委托。考虑以下场景:雇员wang有一个PlayGame事件,雇员li交给wang一个委托,说“你玩游戏的时候告诉我”,然后雇员zhang也交给wang另一个委托:“你玩游戏的时候也告诉我”。那么,雇员wang必须找个方法将所有玩游戏委托都记住,以便通知所有人,以免三缺一。这种“多播委托”(MulticastDelegate)是事件的基本模型,在事件发生的时候由事件触发者通过调用委托来运行未知位置未知名字但已知特征的多个方法。

使用事件跟使用委托有一些区别。首先,符合委托特征的方法有了新名字:事件处理器(event handler),因为它的作用就是处理一个事件。然后,将委托交给事件所有者这个动作叫做“订阅”(subscribe),也就是说事件像周刊一样,发行的时候你就能收到一份。使用事件的步骤是

//1, 定义委托。该委托必须无返回(void),
//  因为事件如果存在多个订阅者,有返回值就乱套了。
//  委托类型的名字习惯用EventHandler或Handler结束,
//  因为这个委托类型代表的是事件处理器。
public delegate void PlayGameEventHandler(Employee starter, string gameName);
// public delegate void 委托类型名(参数列表);

//2,在对象里定义事件,即“委托变量”——多播委托变量
public event PlayGameEventHandler PlayGame;
// public event 委托类型名 事件名;

//3,由其他对象操作,订阅事件
wang.PlayGame += new PlayGameEventHandler(this.wang_PlayGame);
// 取消订阅只需要将上面的 += 改成 -=

// 这个是事件处理器的范例:
private void wang_PlayGame(Employee starter, string gameName)
{ Console.Write("我也要玩" + gameName + "!!"); }

//4,事件发生时,调用所有订阅者的事件处理器:
if (this.PlayGame != null) // 没有人订阅就会 == null
    this.PlayGame(this, "Tic Tac Toe");
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

用const定义常量时所存在的潜在bug,就是在程序中使用dll类库某个类的静态常量时,如果在类库中修改静态常量的值,那么调用的时候就不会发生改变还是原来的值,可以重新编译一下,.而readonly就不会,也不用重新编译一下.
const不用分配内存,而readonly要分配内存

posted on 2008-02-08 17:49  网络小鼠  阅读(385)  评论(0编辑  收藏  举报