类型的事件可以通过System.Type.GetEvents和System.Type.GetEvent方法访问,这两个方法都返回System.Reflection.Eventinfo来描述事件。EventInfo对象有些属性用来表明事件的名称和类型。EventInfo最令人感兴趣的成员是GetAddMethod方法和GetRemoveMethod方法。如图4.6所示,每个方法都会返回一个MethodInfo.依次描述事件的注册方法和取消方法。它们能够接收一个布尔值,用于控制是否返回非公有方法。
像属性的方法一样,事件的方法将使用specialname元数据特性进行标记,以防止对它的直接调用。大多数编程语言都的自己的语法,用于注册和取消事件句柄。在VB.NET中,你只需要在字段声明中简单地添加WithEvents访问修饰符。在c#中,+=和-=操作行将被重载,分别用于调用注册或者取消事件的力法。
下面的c#代码使用了一个Invoice类型,它有一个System.EventHandler类型的名为OnSubmit的事件
using System;
public sealed class Utils {
public static void FinisIt(invoice inv,EventHandler eh){
inv.OnSubmit += eh; //调用 "add”方法
inv.CompleceWork();// 进行可能产生事件的工作
inv.OnSubmit -= eh; //调用"remove"方法
}
}
尽管其语法过于精练,但c#编译器将发射对底层add和remove方法的调用,它们在元数据中被指定用于 OnSubmit事件。
像属性一样,每种编程语言都创建了各自的语法,用于将事件定义为类型的成员。在c#中,其语法与属性定义的语法非常相似。考察下面的c#类型声明:
C#还提供了用于声明事件的缩略语法。下面的类声明等价于前面的示例
Using System;
Public sealed class Invoice{
Public event EventHandler OnSubmit;
}
不管这两个例了中的哪一个,c#编浑器都会发射两个具有如下签名的方法定义
public voLd add_OnSubmit(EventHandler value) ;
public voLd remove_OnSubmit(EventHandler value);
注意,第一个例子使用了System.Delegate.Combine方法和System.Delegate.Remove方法,相关内容将在第6章中详细讨论。
最后一个要讨论的成员种类是索引属性。如果一个属性的方法接收的参数不是settef方法的标准值参数 这个属性就被称为索引属性(indexed property)。对于Visual Basic的传统版本来说,索引属性是一个倒退。而VB.NET被完全支持索引属性,c#部分支持索引属性。
c#中的每个类型只支持一个索引属性。这个属性被称为索引器(indexer),并且必须使用[System.Reflection.DefaultMember.Attribute]将它标记为类型的“默认”成员,索引器与其他任何属性相似,可以有一个get方法或者一个set方法(或两者都有)。C#的索引器在两个方面不同于其他属性:其一,索引器可以接收一个或多个参数,实际上它能够被重载,其二,不像任何其他属性.C#中的索引器不能定义为静态的。
许多编程语言使用数组语法公开索引器。例如,下面的代码使用了一个被称为InvoiceLines的类型,它有一个decimal类型的索引器。索引器的参数是一个字符串,它对应于一个简单的零件号码。
public sealed class Utils {
public static void Adjust{
iq[“widget”]=3;//调用set方法
decimal cs=iq[“gizmo”];//调用cet方法
iq[“doodad”]=cs*2;//调用Ref方法
}
}
如该例所示,索引器允许变量被作为关联的数组处理每种编程语言都有其自己的定义索引器的语法,下面是一个用C#定义索引器的示例:
如同这个示例中的注释所示,底层的属性名将会是Ttem个名字是由c#编译器选定的,而名字的选择一般无关紧要。某些语言(例如,VB.NET)允许通过名字显式地访问类型的索引器。在那些语言中,索引器名字的选择是很重要的,如果要控制索引器的名字,则可以使用[System.Runtime.CompilerServices.IndexerName]特性。例如,当要使用名字QUantities产生刚才定义的索引器,可以像下面这样声明索引器:
[
System.Runtime.CompileerServices.IndexerName(“Quantities”)
]
Public Decimal this[string partID]
{
//剩余部分与前面的一样……
经过这样的修改,VB.NET程序员可以像下面这样使用这个类型
Public Sub Adjust(iq as InvoiceLines)
iq(“widget”)=3
iq.Quantities(“widget”)=3 和上一行一样!
End Sub
属性、索引器和事件都是附加的元数据提示(hint),用于传达一个或多个方法的预定用法。它们的使用完全是可选的。Qpenc購汵CQpenc(ueg\購$N*N筫誰褈歔0R