12
votes

Type Inference pour API fluide

J'ai les méthodes d'extension suivantes: xxx pré>

Les interfaces génériques sont toujours dérivées de leur interface non générique correspondante. P>

Malheureusement, pour faire ce travail:

public static void FooBar<TResult>(
    this IBar<TResult> bar, Action<TResult> action);


8 commentaires

Y a-t-il une raison dans votre API fluide d'avoir les méthodes non génériques? Sinon, il suffit de les abandonner en faveur des génériques entièrement.


Pourquoi n'avez-vous pas de Static Static ibar bar (cette IFOO FOO); ?


@Chris: Malheureusement oui, que dois-je revenir à FOO (action)?


@supercat: Non requis par les utilisateurs, alors pourquoi le mettre en œuvre? Malheureusement, si je souhaite utiliser l'inférence de type, je dois la mettre en œuvre ... question est maintenant: comment surmonter cette faille?


Je n'appellerais pas du tout un "défaut". Je pense que votre meilleur pari est de mettre en œuvre toutes les méthodes ou de créer un constructeur générique d'emballage dans lequel le treesult est défini une fois au niveau de la classe. (Ce faisant, je suppose que je veux dire cependant l'utilisation de la méthode de prolongation, et vous oblige toujours à mettre en œuvre les méthodes) Je dis simplement mordre la balle, faites-le approprié et évitez "Magic". EDIT: Désolé, je pense que je comprends bien le problème maintenant. Vous devez chaîner les informations génériques à travers des appels non génériques. Ouais, essayez de faire une classe de constructeurs distincte.


@Chris: Merci de votre réponse, cependant, il y a aussi beaucoup de barres () - comme des méthodes non écrites par moi, mais par des développeurs de vulgarisation. Je ne veux pas qu'ils ont besoin de mettre en œuvre deux méthodes.


Les types de la question de la question ne font pas appliquer la sécurité de type, si "X devrait être de type". Le suivant Typecheck: Action stringaction = console.writeine; api.foo (x => retourlong ()). bar (). Foobar (stringaction);


@ D.R. Si vous abandonnez les interfaces non génériques, vous utiliseriez l'unité type comme T. L'unité type est le type avec une seule valeur, qui peut être implémentée comme Unité de structure publique {} . Vous remarquerez également que le compilateur ne peut pas discerner entre les surcharges de action et Func <> ou entre action et et et Func , vous voudrez donc renommer l'un des foo s.


4 Réponses :


4
votes

En supposant que vous soyez capable d'aller d'un ifoo code> à un ifoo code> et votre chaîne de méthodes ne se soucie pas de treesult code> Vous pourrez peut-être enregistrer une partie de la mise en œuvre en modifiant l'utilisation de quelque chose comme:

api.Foo(x => ReturnLong())
   .Bars(foo=>foo.Bar1() //where foo is an IFoo
                 .Bar2()
                 .Bar3()
                 ...
    )
   .FooBar(x => ...);


1 commentaires

On pourrait faire cela, cependant, il y a beaucoup de bruit. Bien qu'il existe de nombreuses méthodes de barre () différentes, la plupart du temps, l'utilisateur va appeler exactement un et cela se traduirait .bars (foo => foo.bar ()) pour rien: / merci pour la tentative -> upvoted.



1
votes

L'interface fluide au sein de C # dépend des types (explicitement ou implicitement) étant passée à travers chaque . . Comme vous l'avez décrit, si vous perdez des informations de type, vous ne pouvez pas le récupérer.

Vos seules options sont d'avoir des succursales dans vos expressions, comme décrit dans la réponse de Shawn, ou si vous devez avoir ibar bar (ce iFOO FOO) seulement, donc que les informations de type nécessaires sont toujours transmises.

  • Bien sûr, si certains de vos .bar s sont en fait comme .First ou .Singleordfault Ils ne doivent pas être suivis par < code> .foobar de toute façon (au moins pas directement).

0 commentaires

0
votes

Notez que le type générique doit être connu à l'heure de la compilation. Vous pouvez stocker l'instance de classe de type au moment de l'exécution mais vous pouvez 't l'utiliser à la place du paramètre générique.

Vous avez créé deux types: ifoo code> et ifoo : ifoo code>. Toutefois, la classe ibar code> est créée par le ifoo code> qui ne dispose pas des informations sur son type, car elle n'engage aucun. Ainsi, les informations de type sont perdues. Nous ne pouvons considérer que des solutions capables de déduire le type au moment de la compilation. P>


La première solution est connue pour vous - créer une version générique de tous types que vous utilisez dans votre chaîne d'invocation. . Cela nécessite beaucoup d'effort. P>


Si vous pouvez supposer, que le type ne changera pas pendant l'exécution, vous pouvez envelopper ce type et utiliser vos méthodes explicitement: p>

.
.
.FooBar(x => { if (x is MyType) { /* ... */ } });


0 commentaires

2
votes

Débarrassez-vous de l'interface IFOO qui n'a pas de paramètre de type et ajoutez un paramètre de type à IBAR pour vous rappeler le type d'IFOO. Sans cela, des programmes incorrects de type chèque. xxx


0 commentaires