委托声明和使用
-
delegate-declaration:(委托声明:)
- attributesopt delegate-modifiersopt delegate return-type identifier ( formal-parameter-listopt ) ;(属性 可选 委托修饰符 可选 delegate 返回类型 标识符 ( 形参表 可选 ) ;) delegate-modifiers:(委托修饰符:)
-
delegate-modifier(委托修饰符)
delegate-modifiers delegate-modifier(委托修饰符 委托修饰符)
delegate-modifier:(委托修饰符:)
-
new
public
protected
internal
private
同一修饰符在一个委托声明中多次出现属于编译时错误。
new
修饰符仅允许在其他类型中声明的委托上使用,在这种情况下该修饰符表示所声明的委托会隐藏具有相同名称的继承成员。
public
、protected
、internal
和 private
修饰符控制委托类型的可访问性。根据委托声明所在的上下文,可能不允许使用其中某些修饰符。
上述的语法产生式中,标识符用于指定委托的类型名称。
可选的形参表用于指定委托的参数,而返回类型则指定委托的返回类型。如果下面两个条件都为真,则方法和委托类型是兼容的:
- 它们具有相同的参数数目,并且类型相同,顺序相同,参数修饰符也相同。
- 它们的返回类型相同。
C# 中的委托类型是名称等效的,而不是结构等效的。具体地说,对于两个委托类型,即使它们具有相同的参数列表和返回类型,仍被认为是不同的两个委托类型。不过,这样两个彼此不同的但结构上又相同的委托类型,它们的实例在比较时可以认为是相等关系。
例如:
delegate int D1(int i, double d); class A { public static int M1(int a, double b) {...} } class B { delegate int D2(int c, double d); public static int M1(int f, double g) {...} public static void M2(int k, double l) {...} public static int M3(int g) {...} public static void M4(int g) {...} }
委托类型 D1
和 D2
都与方法 A.M1
和 B.M1
兼容,这是因为它们具有相同的返回类型和参数列表;但是,这些委托类型是两个不同的类型,所以它们是不可互换的。委托类型 D1
和 D2
与方法 B.M2
、B.M3
和 B.M4
不兼容,这是因为它们具有不同的返回类型或参数列表。
声明一个委托类型的唯一方法是通过委托声明。委托类型是从 System.Delegate
派生的类类型。委托类型隐含为 sealed
,所以不允许从一个委托类型派生任何类型。也不允许从 System.Delegate
派生非委托类类型。请注意:System.Delegate
本身不是委托类型;它是从中派生所有委托类型的类类型。
C# 设置了专门的语法用于委托类型的实例化和调用。除实例化外,所有可以应用于类或类实例的操作也可以相应地应用于委托类或委托实例。具体说来,可以通过通常的成员访问语法访问 System.Delegate
类型的成员。
委托实例所封装的方法集合称为调用列表。从某个方法创建一个委托实例时,该委托实例将封装此方法,此时,它的调用列表只包含一个进入点。但是,当组合两个非空委托实例时,它们的调用列表被连接在一起(按照左操作数在先、右操作数在后的顺序)以组成一个新的调用列表,它包含了两个或更多个“进入点”。
委托是使用二元 +和 += 运算符来组合的。可以使用一元 -和 -= 运算符将一个委托从委托组合中移除。委托间还可以进行比较以确定它们是否相等。
下面的示例显示多个委托的实例化及其相应的调用列表:
delegate void D(int x); class C { public static void M1(int i) {...} public static void M2(int i) {...} } class Test { static void Main() { D cd1 = new D(C.M1); // M1 D cd2 = new D(C.M2); // M2 D cd3 = cd1 + cd2; // M1 + M2 D cd4 = cd3 + cd1; // M1 + M2 + M1 D cd5 = cd4 + cd3; // M1 + M2 + M1 + M1 + M2 } }
实例化 cd1
和 cd2
时,它们分别封装一个方法。实例化 cd3
时,它的调用列表有两个方法 M1
和 M2
,而且正是这样的顺序。cd4
的调用列表包含 M1
、M2
和 M1
,顺序与此相同。最后,cd5
的调用列表包含:M1
、M2
、M1
、M1
和 M2
,顺序与此相同