Al aprender más sobre el modelo de eventos estándar en .NET, descubrí que antes de introducir genéricos en C#, el método que manejará un evento está representado por este tipo de delegado:
// // Summary: // Represents the method that will handle an event that has no event data. // // Parameters: // sender: // The source of the event. // // e: // An object that contains no event data. public delegate void EventHandler(object sender, EventArgs e);Pero después de que se introdujeron los genéricos en C# 2, creo que este tipo de delegado se reescribió usando genericidad:
// // Summary: // Represents the method that will handle an event when the event provides data. // // Parameters: // sender: // The source of the event. // // e: // An object that contains the event data. // // Type parameters: // TEventArgs: // The type of the event data generated by the event. public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);Tengo dos preguntas aquí:
Primero, ¿por qué el parámetro de tipo TEventArgs no se hizo contravariante ?
Si no me equivoco, se recomienda hacer que los parámetros de tipo que aparecen como parámetros formales en la contravariante de la firma de un delegado y el parámetro de tipo que será el tipo de retorno en la covariante de la firma del delegado.
En el libro de Joseph Albahari, C# en pocas palabras, cito:
Si está definiendo un tipo de delegado genérico, es una buena práctica:
- Marque un parámetro de tipo usado solo en el valor de retorno como covariante (fuera).
- Marque cualquier parámetro de tipo usado solo en parámetros como contravariante (in).
Hacerlo permite que las conversiones funcionen de forma natural al respetar las relaciones de herencia entre los tipos.
Segunda pregunta: ¿Por qué no hubo una restricción genérica para hacer cumplir que los TEventArgs derivan de System.EventArgs ?
Como sigue:
public delegate void EventHandler<TEventArgs> (object source, TEventArgs e) where TEventArgs : EventArgs;Gracias por adelantado.
Editado para aclarar la segunda pregunta:
Parece que la restricción genérica en TEventArgs ( donde TEventArgs: EventArgs ) estaba allí antes y Microsoft la eliminó, por lo que aparentemente el equipo de diseño se dio cuenta de que no tenía mucho sentido práctico.
Edité mi respuesta para incluir algunas de las capturas de pantalla de