Pourquoi utiliser une méthode générique avec une contrainte de type au lieu du type lui-même?

14

Dans une autre question StackExchange, j'ai remarqué quelqu'un utilisant ce prototype:

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

En gardant à l'esprit qu'il n'y a qu'une seule contrainte de type ( SomeSpecificReferenceType), quelle est la différence et l'avantage de l'écrire comme ça, au lieu de simplement:

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

Dans les deux cas, argsera soumis à une vérification de type au moment de la compilation. Dans les deux cas, le corps de la méthode peut s'appuyer en toute sécurité sur des connaissances qui argsont (ou qui sont des descendants) d'un type spécifique connu au moment de la compilation.

Est-ce le cas d'un développeur trop zélé qui apprend les génériques avant d'apprendre l'héritage ordinaire? Ou existe-t-il une raison légitime pour qu'une signature de méthode soit écrite de cette façon?

John Wu
la source
Je connais à peine C # donc ce n'est qu'une supposition, mais cela ne permet-il pas une répartition statique plus efficace au lieu d'une répartition dynamique?
Anton Barkovsky

Réponses:

13

Est-ce le cas d'un développeur trop zélé qui apprend les génériques avant d'apprendre l'héritage ordinaire?

Oui, c'est probablement le cas.

Ou y a-t-il une raison légitime pour qu'une signature de méthode soit écrite de cette façon?

Peut-être . En général, cela aurait plus de sens s'il y avait une valeur de retour impliquée Tou un autre paramètre utilisé T.

Mais, il est possible que les éléments internes du code utilisent T(peut-être comme argument pour un sérialiseur?) Et aient besoin d'utiliser spécifiquement Tet non la classe de contraintes. Vous verrez parfois que lorsque la contrainte est une interface associée à la newcontrainte et que les entrailles de la méthode créent des Ts pour une raison quelconque.

Donc, bien qu'il soit rare de voir la version de contrainte nécessaire, il y a des moments où elle l'est. Et il est toujours possible que la méthode utilisée pour en avoir besoin, mais fait maintenant pas et le développeur gauche comme est de ne pas introduire un changement de rupture.

Telastyn
la source
1

Je pense que je me souviens avoir tapé une réponse contenant ceci.

À cette époque, la raison était la suivante:
(Le code peut être différent. Juste pour illustrer l'une des raisons possibles pour lesquelles il existe une contrainte sur le paramètre type dans une méthode générique.)

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

Fondamentalement, le code entre lui-même dans les manipulations de type de codage manuel. Il peut également être mélangé à des éléments de réflexion.

Par exemple, en utilisant Method<T>(T arg) where T : ..., on peut remplacer arg.GetType()par typeof(T). Cependant, je ne sais pas si ce choix est bon ou mauvais.

Je suppose que ce n'est qu'un exemple de l'auteur (peut-être moi ou quelqu'un d'autre) qui ne réfléchit pas soigneusement à toutes les possibilités de codage, tout en se concentrant trop sur une question / un problème différent.

rwong
la source
msgstr "on peut remplacer arg.GetType () par typeof (T)". Ceci est utile lorsque arg peut être valablement nul, par exemple dans certains cas de sérialisation.
walpen