Red de conocimiento informático - Conocimiento sistemático - Análisis en profundidad de eventos en programación C#

Análisis en profundidad de eventos en programación C#

Un evento es un miembro que permite que un objeto o clase proporcione anuncios. Los usuarios pueden agregar código ejecutable al evento proporcionando un controlador de eventos. Los eventos utilizan declaraciones de eventos para declarar un evento. una declaración de dominio de evento o puede ser una declaración de propiedad de evento. En cada caso, la declaración puede consistir en un conjunto de propiedades, el nuevo modificador, una combinación válida de los cuatro modificadores de acceso y un modificador estático. El tipo de declaración de evento debe ser. un tipo representativo y ese tipo representativo deben ser al menos iguales. El evento en sí también es accesible. Una declaración de dominio de evento corresponde a una declaración de dominio que declara uno o más campos de tipo representativo. El modificador de solo lectura no está permitido en una declaración de dominio de evento. Una declaración de atributo de evento corresponde a una declaración de propiedad que declara un atributo de tipo representativo. En consecuencia, excepto para las declaraciones de propiedad de evento que contienen accesores get y set, los nombres de miembros y las declaraciones de acceso son los mismos para esas declaraciones de propiedad y los modificadores abstractos y de anulación virtual son los mismos. no permitido en una declaración de miembro de clase o evento que contiene una declaración de miembro de evento. El miembro de evento en el literal de programa de una estructura está asociado con un campo privado o propiedad del tipo representado. Este miembro se puede usar en cualquier contexto que permita la. uso de campos o propiedades Si una clase o estructura contiene un miembro de evento fuera del literal del programa, el miembro de evento se declara solo. Puede usarse como el operando derecho de los operadores = y = (§). adjuntar o eliminar un controlador de eventos a un miembro del evento. El operador de acceso para este miembro del evento controla el contexto en el que se realiza la operación ya que = y = son las únicas operaciones que se pueden usar en eventos fuera del tipo en el que se encuentran los miembros del evento. se declaran. El código externo puede agregar o eliminar identificadores de un evento, pero no puede obtener ni modificar los valores de los campos básicos del evento o las propiedades del evento de ninguna otra manera. En el ejemplo public delegado void EventHandler (objeto remitente Event e); Botón de clase: Control{ evento público EventHandler Click; protected void OnClick(Event e) {if (Click!= null) Click(this e); public void Reset() {Click = null }} uso del campo de evento Click en la clase Button. Como ejemplo de demostración, este campo se puede verificar en la expresión de llamada de delegado. Modificar y generar el evento Click usando el método OnClick en la clase Button. La llamada del miembro del evento. Los delegados representados son exactamente los mismos, por lo que no hay construcciones de lenguaje especiales para generar el evento. Tenga en cuenta que la llamada al delegado se realiza verificando que el delegado no sea nulo. Click solo se puede usar en el lado derecho de los operadores = y = fuera de la declaración de la clase Button. De la siguiente manera b Click = new EventHandler( ); agrega un delegado a la lista de llamadas del evento Click y b Click =; new EventHandler( );

Elimina un delegado de la lista de llamadas del evento Click. El resultado de una operación de la forma x = y o x = y cuando x es un miembro del evento y se produce la referencia. fuera del tipo declarado que contiene x es nulo (el inverso del valor de x después de la asignación. Esta regla prohíbe externos El código verifica directamente la representación básica del miembro del evento

El siguiente ejemplo describe cómo funciona el controlador de eventos). se adjunta a una instancia de la clase Botón arriba

clase pública LoginDialog: Formulario{Button OkButton;

CancelButton; public LoginDialog() {OkButton = nuevo Botón( ); OkButton Click = nuevo EventHandler(OkButtonClick); CancelButton = nuevo Botón( ); CancelButton Click = nuevo EventHandler(CancelButtonClick } void OkButtonClick(objeto remitente Evento) {/ / Manejar el evento OkButton Click } void CancelButtonClick(object sender Event e) {// Manejar el evento CancelButton Click }} Aquí el constructor LoginDialog crea dos instancias de Botón y adjunta el identificador del evento al evento Click. El miembro del evento es un campo típico como el anterior. Como se muestra en el ejemplo del Botón, no es aceptable que cada evento consuma un campo de almacenamiento. Una clase podría declarar propiedades del evento en lugar del campo del evento y usar un mecanismo privado para almacenar la representación básica (imagínese que en algunos casos la mayoría). eventos No es aceptable usar un campo para cada evento que no se maneja. La capacidad de usar propiedades en lugar de campos permite a los desarrolladores lograr un compromiso entre espacio y tiempo) En el ejemplo clase Control: Componente{ // Claves únicas para eventos. objeto estático de solo lectura mouseDownEventKey = new object(); objeto estático de solo lectura mouseUpEventKey = new object(); // Devuelve el controlador de eventos asociado con la clave protegida Delegado GetEventHandler(objeto clave) { } // Establece el controlador de eventos asociado con la clave protegida void SetEventHandler(objeto) key Delegate handler) { } // propiedad del evento MouseDown evento público MouseEventHandler MouseDown {get { return (MouseEventHandler)GetEventHandler(mouseDownEventKey }set { SetEventHandler(mouseDownEventKey value }} // propiedad del evento MouseUp evento público MouseEventHandler MouseUp {get {); return (MouseEventHandler)GetEventHandler(mouseUpEventKey);}set { SetEventHandler(mouseUpEventKey value);}}}

El control de clases proporciona un método de mecanismo de almacenamiento interno para eventos. SetEventHandler utiliza una clave para relacionarse con el valor representativo. GetEventHandler devuelve la generación actual asociada con la clave

El mecanismo de almacenamiento básico de la tabla está diseñado para asociar el tipo de representación vacío con la clave y no habrá consumo. Por lo tanto, los eventos sin identificadores no ocupan espacio de almacenamiento.

Función de inicialización de variable de instancia Cuando lo hace un constructor. no construir una función de inicialización O una función de inicialización del constructor de la forma base (). El constructor realiza implícitamente la inicialización especificada por la función de inicialización variable del campo de instancia declarado en la clase. Esto está relacionado con la secuencia de asignación. en el constructor de clase base directa. La función de inicialización de variable se ejecuta directamente en la entrada del constructor antes de la llamada. La ejecución del constructor se ejecuta en el orden en que aparecen en la declaración de clase. La función se puede considerar como insertada automáticamente en el cuerpo del constructor. Ejemplo antes de la primera declaración

Usando colecciones del sistema; A(int n) {count = n;}} clase B: A{double sqrt = Math Sqrt(); ArrayList items = new ArrayList(); int max public B(): this() {items Add(predeterminado) ;} public B(int n): base(n ) {max = n; }}

Contiene varios inicializadores de variables y también contiene inicializadores de constructor para cada formulario (base y this). relacionado con el ejemplo presentado a continuación donde cada El comentario especifica una declaración de inserción automática (la sintaxis utilizada para insertar automáticamente llamadas al constructor no es válida al menos para demostrar este mecanismo)

Usando colecciones de sistema clase A{; int x y count; public A() {x = ; // Inicializador de variable = ; // Inicializador de variable() // Invocar objeto() constructorcount = } public A(int n) {x = ; ; // Variable inicializadorobject(); // Invocar objeto() constructorcount = n; }}clase B: A{ double sqrt; int max; B(int) constructoritems Agregar( predeterminado ); } public B(int n): base(n) {sqrt = Math Sqrt( ); // Variable inicializeritems = new ArrayList( ); Invocar A(int) constructormax = n ; }}

Tenga en cuenta que la función de inicialización de la variable se convierte en una declaración de asignación y que la declaración de asignación se ejecuta antes de la llamada al constructor de la clase base. todos los campos de la instancia se reemplazan por los suyos antes de que se ejecute cualquier declaración que acceda a la instancia. Ejemplo de inicialización de la función de inicialización variable

clas.

s A{ public A() {PrintFields(); } public virtual void PrintFields() {}}clase B: A{ int x = ; int y; public B() {y = ; } anulación pública void PrintFields() { Console WriteLine( x = { } y = { } x }}

Cuando se usa new B() para crear una instancia de B, se produce el siguiente resultado x = y =

<); p > Debido a que la función de inicialización de variables se ejecuta antes de llamar al constructor de la clase base, el valor de x es pero el valor de y es (el valor predeterminado de int. Esto se debe a que la asignación a y no se ejecuta hasta la clase base). constructor devuelve. Si el constructor predeterminado Una clase que no contiene ninguna declaración de constructor proporcionará automáticamente un constructor predeterminado. El constructor predeterminado suele tener la siguiente forma

public C(): base() {} <. /p>

Aquí C es el nombre de la clase. El constructor predeterminado llama completamente al constructor sin parámetros de la clase base directa. Si no hay ningún constructor sin parámetros accesible en la clase base directa, se producirá un error.

class Message{object sender; string text;}

Debido a que la clase no contiene una declaración de constructor, se proporciona un constructor predeterminado, por lo que este ejemplo es equivalente a class Message{ object sender ; string text; public Message(): base() {}}

Constructor privado Cuando una clase solo declara un constructor privado, otras clases no pueden derivar de esta clase ni crear instancias de la clase. generalmente se usa en Por ejemplo, en una clase que solo contiene miembros estáticos

public class Trig{private Trig() {} // Evitar la creación de instancias public const double PI = ; public static double Sin(double x) { }public static double Cos(double x) { }public static double Tan(double x) { }} La clase Trig proporciona un conjunto de métodos y constantes relacionados pero no tiene instancias, por lo que declara un constructor privado separado. Tenga en cuenta que al menos. se debe declarar un constructor privado Evite generar automáticamente un constructor predeterminado (que generalmente tiene accesibilidad pública) Parámetros opcionales del constructor La forma this() de un constructor generalmente se usa en relación con la implementación de parámetros opcionales del constructor en este ejemplo clase Texto{texto público(). ): this(null) {} public Text(int x int y): this(x y null) {}public Text(int x int y string s) {// Implementación real del constructor }}Los dos primeros El primer constructor simplemente proporciona valores predeterminados para los parámetros faltantes. Ambos usan una función de inicialización del constructor this() para llamar al tercer constructor. En realidad, hace el trabajo de inicializar la nueva instancia. El efecto es que pueden seleccionar el parámetro del constructor Texto t = nuevo Texto. (); // Igual que Texto( nulo

l)Texto t = nuevo Texto( ); // Igual que Texto( nulo)Texto t = nuevo Texto( Hola ); Un destructor es un miembro que implementa el comportamiento de destruir una instancia de una clase. La declaración del constructor se utiliza para declarar un destructor. El identificador declarado debe tener el nombre de la clase en la que se declara el destructor. Se produce un error si se especifica cualquier otro nombre. El cuerpo de la declaración del destructor se especifica para inicializar una nueva instancia. de la clase La declaración ejecutada está relacionada con el cuerpo de un método de instancia con un tipo de retorno nulo. Ejemplo clase Prueba{ static void Main() {A F();}} class A{ static A(); Consola WriteLine( Init A) } public static void F() {Consola WriteLine( A F }}clase B{ static B() {Console WriteLine( Init B } public static void F() {Consola WriteLine( B F); }} generará O la siguiente salida Init AA FInit BB F o la siguiente salida Init BInit AA FB F lishixinzhi/Article/program/net/201311/12463