CATEGORII DOCUMENTE |
Delegates enable scenarios that other languages-such as C++, Pascal, and Modula-have addressed with function pointers. Unlike C++ function pointers, delegates are fully object oriented; unlike C++ pointers to member functions, delegates encapsulate both an object instance and a method.
A delegate declaration defines a class that derives from the class System.Delegate. A delegate instance encapsulates one or more methods, each of which is referred to as a callable entity. For instance methods, a callable entity consists of an instance and a method on the instance. For static methods, a callable entity consists of just a method. Given a delegate instance and an appropriate set of arguments, one can invoke all of that delegate's instance's methods with that set of arguments.
An interesting and useful property of a delegate instance is that it does not know or care about the classes of the methods it encapsulates; all that matters is that the methods are compatible (15.1) with the delegate's type. This makes delegates perfectly suited for "anonymous" invocation.
A delegate-declaration is a type-declaration (9.5) that declares a new delegate type.
delegate-declaration:
attributesopt
delegate-modifiersopt
delegate return-type identifier
( formal-parameter-listopt ) ;
delegate-modifiers:
delegate-modifier
delegate-modifiers delegate-modifier
delegate-modifier:
new
public
protected
internal
private
It is an error for the same modifier to appear multiple times in a delegate declaration.
The new modifier is only permitted on delegates declared within another type. It specifies that the delegate hides an inherited member by the same name, as described in 10.2.2.
The public, protected, internal, and private modifiers control the accessibility of the delegate type. Depending on the context in which the delegate declaration occurs, some of these modifiers may not be permitted (3.5.1).
The delegate's type name is identifier.
The optional formal-parameter-list specifies the parameters of the delegate, and return-type indicates the return type of the delegate. A method and a delegate type are compatible if their formal-parameter-lists contain the exact same order, number, and types of parameters, same parameter modifiers, and their return-types are the same. Delegate types in C# are name equivalent, not structurally equivalent. (However, note that instances of two distinct but structurally equivalent delegate types may compare as equal (7.9.8).) Specifically, two different delegate types that have the same parameter lists and signature and return type are considered different delegate types.
For example:
delegate int D1(int i, double d);
class A
}
class B
public static void M2(int k, double l)
public static int M3(int g)
public static void M4(int g)
}
The delegate types D1 and D2 are both compatible with the methods A.M1 and B.M1, since they have the same return type and parameter list; however, these delegate types are two different types, so they are not interchangeable. The delegate types D1 and D2 are incompatible with the methods B.M2, B.M3, and B.M4, since they have different return types or parameter lists.
The only way to declare a delegate type is via a delegate-declaration. A delegate type is a class type that is derived from System.Delegate. Delegate types are implicitly sealed, so it is not permissible to derive any type from a delegate type. It is also not permissible to derive a non-delegate class type from System.Delegate. Note that System.Delegate is not itself a delegate type; it is a class type from which all delegate types are derived.
C# provides special syntax for delegate instantiation and invocation. Except for instantiation, any operation that can be applied to a class or class instance can also be applied to a delegate class or instance, respectively. In particular, it is possible to access members of the System.Delegate type via the usual member access syntax.
The set of methods encapsulated by a delegate instance is called an invocation list. When a delegate instance is created (15.2) from a single method, it encapsulates that method, and its invocation list contains only one entry. However, when two non-null delegate instances are combined, their invocation lists are concatenated-in the order left operand then right operand-to form a new invocation list, which contains two or more entries.
Delegates are combined using the binary + (7.7.4) and += operators (7.13.2). A delegate can be removed from a combination of delegates, using the binary - (7.7.5) and -= operators (7.13.2). Delegates can be compared for equality (7.9.8).
The example
delegate void D(int x);
class C
public static void M2(int i)
}
class
Test
}
shows the instantiation of a number of delegates, and their corresponding invocation lists. When cd1 and cd2 are instantiated, they each encapsulate one method. When cd3 is instantiated, it has an invocation list of two methods, M1 and M2, in that order. cd4's invocation list contains M1, M2, and M1, in that order. Finally, cd5's invocation list contains M1, M2, M1, M1, and M2, in that order. For more examples of combining (as well as removing) delegates, see 15.3.
An instance of a delegate is created by a delegate-creation-expression (7.5.10.3). The newly created delegate instance then refers to either:
The static method referenced in the delegate-creation-expression, or
The target object (which cannot be null) and instance method referenced in the delegate-creation-expression, or
Another delegate
For example:
delegate void D(int x);
class C
public void M2(int i)
}
class
Test
}
Once instantiated, delegate instances always refer to the same target object and method. When two delegates are combined, or one is removed from another, a new delegate results with its own invocation list; the invocation lists of the delegates combined or removed remain unchanged.
C# provides special syntax for invoking a delegate. When a non-null delegate instance whose invocation list contains one entry is invoked, it invokes the one method with the same arguments it was given, and returns the same value as the referred to method. See 7.5.5.2 for detailed information on delegate invocation. If an exception occurs during the invocation of such a delegate, and the exception is not caught within the method that was invoked, the search for an exception catch clause continues in the method that called the delegate, as if that method had directly called the method to which the delegate referred.
Invocation of a delegate instance whose invocation list contains multiple entries proceeds by invoking each of the methods on the invocation list, synchronously, in order. Each method so called is passed the same set of arguments as was given to the delegate instance. If such a delegate invocation includes reference parameters (10.5.1.2), each method invocation will occur with a reference to the same variable; changes to that variable by one method in the invocation list will be visible to methods further down the invocation list. If the delegate invocation includes output parameters or a return value, their final value will come from the invocation of the last delegate in the list.
If an exception occurs during processing of the invocation of such a delegate, and the exception is not caught within the method that was invoked, the search for an exception catch clause continues in the method that called the delegate, and any methods further down the invocation list are not invoked.
Attempting to invoke a delegate instance whose value is null results in an exception of type System.NullReferenceException.
The following example shows how to instantiate, combine, remove, and invoke delegates:
delegate void D(int x);
class C
public static void M2(int i)
public void M3(int i)
}
class
Test
}
As shown in the statement cd3 += cd1;, a delegate can be present in an invocation list multiple times. In this case, it is simply invoked once per occurrence. In an invocation list such as this, when that delegate is removed, the last occurrence in the invocation list is the one actually removed.
Immediately prior to the execution of the final statement, cd3 -= cd1;, the delegate cd3 refers to an empty invocation list. Attempting to remove a delegate from an empty list (or to remove a non-existent delegate from a non-empty list) is not an error.
The output produced is:
C.M1: -1
C.M2: -2
C.M1: 10
C.M2: 10
C.M1: 20
C.M2: 20
C.M1: 20
C.M1: 30
C.M2: 30
C.M1: 30
C.M3: 30
C.M1: 40
C.M2: 40
C.M3: 40
C.M1: 50
C.M2: 50
C.M1: 60
C.M1: 60
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1197
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved