Respondendo a pergunta desta terça-feira: porque este código está errado?

delegate void MeuDelegate<in T>(T t) where T : struct;

Esse delegate leva a crer que eu conseguiria ser contravariante em tipos de estrutura. Só que contravariância não funciona com structs, e há uma razão para isso: structs não possuem herança. No máximo, podem implementar interfaces.

Dessa forma, se tivesse implementado meu delegate assim:

delegate void MeuDelegate<in T>(T t)

Então, dadas estas classes:

    class C
    {
    }
    class Ca : C
    {
    }

Eu poderia chamar o delegate desta forma:

MeuDelegateCerto<C> umDel = c => Console.WriteLine(c.ToString());
MeuDelegateCerto<Ca> ca = umDel;

Mas isso é impossível com structs, porque eu não posso fazer isso:

    struct S
    {
    }
    struct Sa : S
    {
    }

E portanto, eu também não posso fazer isso:

MeuDelegate<S> outroDel = s => Console.WriteLine(s.ToString());
MeuDelegate<Sa> sa = outroDel;

E isso tudo leva o meu delegate contravariante com structs ser, na verdade, um grande absurdo.

Esse é um dos motivos que acabo usando structs só em lugares bem simples: não tem herança.

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.