Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

260
Visualizações
Why wasn't TEventArgs made contravariant in the standard event pattern in the .NET ecosystem?

When learning more about the standard event model in .NET, I found that before introducing generics in C#, the method that will handle an event is represented by this delegate type:

//
// 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);

But after generics were introduced in C# 2, I think this delegate type was rewritten using genericity:

//
// 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);

I have two questions here:

First, why wasn't the TEventArgs type parameter made contravariant ?

If I'm not mistaken it is recommended to make the type parameters that appear as formal parameters in a delegate's signature contravariant and the type parameter that will be the return type in the delegate signature covariant.

In Joseph Albahari's book, C# in a Nutshell, I quote:

If you’re defining a generic delegate type, it’s good practice to:

  • Mark a type parameter used only on the return value as covariant (out).
  • Mark any type parameters used only on parameters as contravariant (in).

Doing so allows conversions to work naturally by respecting inheritance relationships between types.

Second question: Why was there no generic constraint to enforce that the TEventArgs derive from System.EventArgs?

As follows:

public delegate void EventHandler<TEventArgs>  (object source, TEventArgs e) where TEventArgs : EventArgs; 

Thanks in advance.

Edited to clarify the second question:

It seems like the generic constraint on TEventArgs (where TEventArgs : EventArgs) was there before and it was removed by Microsoft, so seemingly the design team realized that it didn’t make much practical sense.

I edited my answer to include some of the screenshots from

.NET reference source

enter image description here

over 4 years ago · Santiago Trujillo
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda