CATEGORII DOCUMENTE |
An event is a member that enables an object or class to provide notifications. Clients can attach executable code for events by supplying event handlers.
Events are declared using event-declarations:
event-declaration:
attributesopt
event-modifiersopt event type
variable-declarators ;
attributesopt
event-modifiersopt event type
member-name
event-modifiers:
event-modifier
event-modifiers event-modifier
event-modifier:
new
public
protected
internal
private
static
virtual
sealed
override
abstract
extern
event-accessor-declarations:
add-accessor-declaration
remove-accessor-declaration
remove-accessor-declaration
add-accessor-declaration
add-accessor-declaration:
attributesopt add block
remove-accessor-declaration:
attributesopt remove block
An event-declaration may include a set of attributes (17), a new modifier (10.2.2), an extern modifier (10.7.4), a valid combination of the four access modifiers (10.2.3), and a valid combination of the static (10.5.2), virtual (10.5.3), override (10.5.4), and abstract (10.5.6) modifiers. In addition, an event that includes the override modifier may also include the sealed modifier (10.5.5).
The static, virtual, override, and abstract modifiers are mutually exclusive except in one case. The abstract and override modifiers may be used together so that an abstract event can override a virtual one.
An event declaration may include event-accessor-declarations. However, if it does not, the compiler supplies them automatically.
An event declaration that omits event-accessor-declarations defines one or more events-one for each of the variable-declarators. The attributes and modifiers apply to all of the members declared by such an event-declaration.
An abstract event is declared with an event-declaration that omits event-accessor-declarations. It is an error for an event-declaration to include both the abstract modifier and event-accessor-declarations.
The type of an event declaration must be a delegate-type (4.2), and that delegate-type must be at least as accessible as the event itself (3.5.4).
An event can be used as the left hand operand of the += and -= operators (7.13.3). These operators are used to attach or remove event handlers to or from an event, and the access modifiers of the event control the contexts in which such operations are permitted.
Since += and -= are the only operations that are permitted on an event outside the type that declares the event, external code can add and remove handlers for an event, but cannot in any other way obtain or modify the underlying list of event handlers.
Within the program text of the class or struct that contains the declaration of an event, certain events can be used like fields. To be used in this way, an event must not be abstract, and must not explicitly include event-accessor-declarations. Such an event can be used in any context that permits a field.
In the example
public delegate void EventHandler(object sender, EventArgs e);
public
class Button: Control
public void Reset()
}
Click is used as a field within the Button class. As the example demonstrates, the field can be examined, modified, and used in delegate invocation expressions. The OnClick method in the Button class "raises" the Click event. The notion of raising an event is precisely equivalent to invoking the delegate represented by the event-thus, there are no special language constructs for raising events. Note that the delegate invocation is preceded by a check that ensures the delegate is non-null.
Outside the declaration of the Button class, the Click member can only be used on the left hand side of the += and -= operators, as in
b.Click += new EventHandler();
which appends a delegate to the invocation list of the Click event, and
b.Click -= new EventHandler();
which removes a delegate from the invocation list of the Click event.
In an operation of the form x += y or x -= y, when x is an event and the reference takes place outside the type that contains the declaration of x, the result of the operation has type void (as opposed to the type of x). This rule prohibits external code from indirectly examining the underlying delegate of an event.
The following example shows how event handlers are attached to instances of the Button class above:
public
class LoginDialog: Form
void OkButtonClick(object sender, EventArgs e)
void CancelButtonClick(object sender,
EventArgs e)
}
Here, the instance constructor for LoginDialog creates two Button instances and attaches event handlers to the Click events.
Event declarations typically omit event-accessor-declarations, as in the Button example above. In cases where the storage cost of one field per event is not acceptable, a class can include event-accessor-declarations and use a private mechanism for storing the list of event handlers.
The event-accessor-declarations of an event specify the executable statements associated with adding and removing event handlers.
The accessor declarations consist of an add-accessor-declaration and a remove-accessor-declaration. Each accessor declaration consists of the token add or remove followed by a block. The block associated with an add-accessor-declaration specifies the statements to execute when an event handler is added, and the block associated with a remove-accessor-declaration specifies the statements to execute when an event handler is removed.
Each add-accessor-declaration and remove-accessor-declaration corresponds to a method with a single value parameter of the event type and a void return type. The implicit parameter of an event accessor is named value. When an event is used in an event assignment, the appropriate event accessor is used. If the assignment operator is += then the add accessor is used, and if the assignment operator is -= then the remove accessor is used. In either case, the right hand operand of the assignment operator is used as the argument to the event accessor. The block of an add-accessor-declaration or a remove-accessor-declaration must conform to the rules for void methods described in 10.5.8. In particular, return statements in such a block are not permitted to specify an expression.
Since an event accessor implicitly has a parameter named value, it is an error for a local variable declared in an event accessor to have that name.
In the example
class
Control: Component
// Add event handler associated with key
protected void AddEventHandler(object
key, Delegate handler)
// Remove event handler associated with key
protected void
RemoveEventHandler(object key, Delegate handler)
// MouseDown event
public event MouseEventHandler
MouseDown
remove
}
// MouseUp event
public event MouseEventHandler
MouseUp
remove
}
}
the Control class implements an internal storage mechanism for events. The AddEventHandler method associates a delegate value with a key, the GetEventHandler method returns the delegate currently associated with a key, and the RemoveEventHandler method removes a delegate as an event handler for the specified event. Presumably, the underlying storage mechanism is designed such that there is no cost for associating a null delegate value with a key, and thus unhandled events consume no storage.
When an event declaration includes a static modifier, the event is said to be a static event. When no static modifier is present, the event is said to be an instance event.
A static event is not associated with a specific instance, and it is an error to refer to this in the accessors of a static event. Furthermore, it is an error for a static event to include any of the following modifiers: virtual, abstract, or override.
An instance event is associated with a given instance of a class, and this instance can be accessed as this (7.5.7) in the accessors of the event.
When an event is referenced in a member-access (7.5.4) of the form E.M, if M is a static event, E must denote a type, and if M is an instance event, E must denote an instance.
The differences between static and instance members are discussed further in 10.2.5.
An event declaration may include a valid combination of the static, sealed, virtual, override, and abstract modifiers. An event that includes the override modifier may also include the sealed modifier (10.5.5).
The static, virtual, override, and abstract modifiers are mutually exclusive except in one case. The abstract and override modifiers may be used together so that an abstract event can override a virtual one.
A virtual event declaration specifies that the accessors of the event are virtual. The virtual modifier applies to both accessors of an event.
An abstract event declaration specifies that the accessors of the event are virtual, but does not provide an actual implementation of the accessors. Instead, non-abstract derived classes are required to provide their own implementation for the accessors by overriding the event. Because an accessor for an abstract event declaration provides no actual implementation, its accessor-body simply consists of a semicolon.
An event declaration that includes both the abstract and override modifiers specifies that the event is abstract and overrides a base event. The accessors of such an event are also abstract.
Abstract event declarations are only permitted in abstract classes (10.1.1.1).
The accessors of an inherited virtual event can be overridden in a derived class by including an event declaration that specifies an override modifier. This is known as an overriding event declaration. An overriding event declaration does not declare a new event. Instead, it simply specializes the implementations of the accessors of an existing virtual event.
An overriding event declaration must specify the exact same accessibility modifiers, type, and name as the overridden event.
An overriding event declaration may include the sealed modifier. Use of this modifier prevents a derived class from further overriding the event. The accessors of a sealed event are also sealed.
It is an error for an overriding event declaration to include a new modifier.
Except for differences in declaration and invocation syntax, virtual, override, and abstract accessors behave exactly like a virtual, sealed, override and abstract methods. Specifically, the rules described in 10.5.3, 10.5.4, 10.5.5, and 10.5.6 apply as if accessors were methods of a corresponding form. Each accessor corresponds to a method with a single value parameter of the event type, a void return type, and the same modifiers as the containing event.
When an event declaration includes an extern modifier, the event is said to be an external event. The extern modifier is permitted only on event declarations that include event-accessor-declarations.
Like external methods (10.5.7), external events are implemented externally, using a language other than C#. Because an external event declaration provides no actual implementation, each of the event-accessor-declarations of an event consists of a semicolon.
When an external event includes a DllImport attribute, the event declaration must also include a static modifier.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1158
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved