Por que usar um método genérico com uma restrição de tipo em vez do próprio tipo?

14

Em uma pergunta StackExchange diferente, notei alguém usando este protótipo:

void DoSomething<T>(T arg) where T: SomeSpecificReferenceType
{
    //Code....
}

Tendo em mente que existe apenas uma restrição de tipo único ( SomeSpecificReferenceType), qual é a diferença e a vantagem de escrevê-lo assim, em vez de simplesmente:

void DoSomething(SomeSpecificReferenceType arg)
{
    //Code....
}

Nos dois casos, argestará sujeito à verificação do tipo em tempo de compilação. Nos dois casos, o corpo do método pode confiar com segurança no conhecimento argde (ou descendente de) um tipo específico conhecido no momento da compilação.

É este o caso de um desenvolvedor superzeloz que aprende sobre genéricos antes de aprender sobre herança comum? Ou existe uma razão legítima para que uma assinatura de método seja escrita dessa maneira?

John Wu
fonte
Eu mal conheço C #, então isso é apenas um palpite, mas isso não permite o envio estático mais eficiente em vez do envio dinâmico?
Anton Barkovsky

Respostas:

13

É este o caso de um desenvolvedor superzeloz que aprende sobre genéricos antes de aprender sobre herança comum?

Sim, provavelmente é.

Ou existe uma razão legítima para que uma assinatura de método seja escrita dessa maneira?

Talvez . Geralmente, faria mais sentido se houvesse um valor de retorno envolvido Tou outro parâmetro usado T.

Mas, é possível que as partes internas do código usem T(talvez como argumento para um serializador?) E precisem usar especificamente Te não a classe de restrição. Ocasionalmente, você verá que quando a restrição é uma interface emparelhada com a newrestrição e a coragem do método cria Ts por algum motivo.

Portanto, embora seja raro ver a versão de restrição necessária, há alguns momentos em que é. E é sempre possível que o método utilizado para precisar dele, mas agora não faz e o desenvolvedor deixou-o como é não introduzir uma alteração de quebra.

Telastyn
fonte
1

Acho que me lembro de ter digitado uma resposta contendo isso.

Naquele momento, o motivo era o seguinte:
(O código pode ser diferente. Apenas para ilustrar um dos possíveis motivos pelos quais há uma restrição no parâmetro type em um método genérico).

class SomeSingleton
{
    static Dictionary<Type, List<object>> staticTypeSpecificList;
    public void AddObjectToList<T>(T t) where T : SomeCommonThing
    {
        Type tt = t.GetType();
        List<object> list;
        if (!staticTypeSpecificList.TryGet(tt, out list))
        {
            list = new List<object>();
            staticTypeSpecificList.Add(tt, list);
        }
        list.Add(t);
    }
}

Basicamente, o código entra nas próprias manipulações de tipo de codificação manualmente. Também pode ser misturado com algumas coisas de reflexão.

Por exemplo, usando Method<T>(T arg) where T : ..., pode-se substituir arg.GetType()por typeof(T). No entanto, não sei se essa escolha é boa ou ruim.

Acho que esse é apenas um exemplo do autor (possivelmente eu ou outra pessoa) que não pensa cuidadosamente em todas as possibilidades de codificação, ao mesmo tempo em que se concentra demais em uma questão / questão diferente.

rwong
fonte
"pode-se substituir arg.GetType () por typeof (T)". Isso é útil quando arg pode validamente ser nulo, por exemplo, em alguns casos de serialização.
walpen