12
votes

Ne peut spécifier à la fois une classe de contrainte et la contrainte de «classe» ou «structure»

J'essaie de travailler autour d'un problème moqueur en créant une maquette personnalisée d'idbset.

La maquette personnalisée: xxx

La méthode de création donne une erreur de construction que je n'ai aucune idée sur la façon de résoudre:

ne peut pas spécifier à la fois une classe de contrainte et la contrainte de «classe» ou «structure»

Simplement enlever Classe à partir des contraintes Résultats dans une autre erreur de construction (que je ne comprends pas non plus :().

Les contraintes pour le paramètre de type 'therivitédentité' de la méthode 'tests.dal.dalants.dalants.dalants.dbsetmock.create ()' doit correspondre aux contraintes de paramètre de type "therrogedentité" de la méthode d'interface 'system.data.entity.idbset .Create () '. Envisager d'utiliser une implémentation d'interface explicite à la place.

Quelqu'un peut-il m'aider à construire cette classe?


6 commentaires

Je suis intéressé à en apprendre davantage sur les situations où le message d'erreur vous indique comment résoudre le problème - vous devez envisager d'utiliser une implémentation d'interface explicite comme indice d'erreur - et pourtant, même si le message vous dit Que faire, vous finissez toujours par demander à des personnes sur Internet pour obtenir de l'aide. Que pourrait faire l'équipe du compilateur pour vous permettre de résoudre le problème vous-même?


Probablement rien, je ne suis tout simplement pas assez brillant pour résoudre ces problèmes triviaux. Mes excuses sincères mon grand chef de pensée.


@ERIFLIPPERT Donc, il n'existe aucun moyen de mettre en œuvre cette méthode d'interface par une méthode publique dans ce cas?


@Haxx: J'essaie d'aider. Il n'y a pas d'appel à être sarcastique. Si le message d'erreur n'est pas clair ou inutile, je peux préconiser pour qu'il soit changé plus facilement que vous le pouvez.


@svick: Je ne sais pas; Je ne l'ai pas donné beaucoup de pensée. Je ne connais pas cette interface.


Haha j'ai du mal à croire que, mais pas de mal prévu ici. J'ai eu un sourire sur mon visage en tapant ma réponse. Et si c'était partiellement sarcastique, je ne peux pas vous blâmer car je me sentais stupide assez de lire votre commentaire :)


4 Réponses :


16
votes

Etant donné que le paramètre type est limité à être un locataire , ajout des contraintes Classe ou struct est redondant. Il suffit de supprimer la contrainte de la classe .

Mise à jour : curieusement, il semble y avoir un conflit entre les erreurs de compilateur ici. Si vous «réparez», vous obtenez l'autre, dans une boucle infinie de désespoir. Heureusement, la seconde erreur nous donne également un moyen de sortir: vous pouvez utiliser une implémentation d'interface explicite: xxx

semble pour ne pas être un moyen de mettre en œuvre cette méthode sans à l'aide de la mise en œuvre d'une interface explicite. Si vous en avez besoin dans le cadre de l'interface publique de la classe, je suggère de créer une autre méthode que la mise en œuvre de l'interface transmet à: xxx


2 commentaires

Veuillez vérifier la question, mise à jour avec les résultats de la simple suppression de «classe» dans les listes de contraintes. Merci


Jordao, j'aimerais pouvoir vous remercier plus que d'accepter votre réponse. / Bows gracieusement! Merci beaucoup, je peux continuer!



3
votes

Essayez de supprimer classe à partir de la pièce de méthode, comme celui-ci; xxx

classe, locataire est un code redondant.


2 commentaires

Cela se traduit par l'erreur de construction suivante: les contraintes pour le paramètre de type «Tapedentité» de la méthode 'tests.dal.dalants.dalants.dalants.dalants.dalants.dalants ()' doivent correspondre aux contraintes de type paramètre de type «Tournédentité» de la méthode d'interface ». Data.entity.idbset .Create () '. Pensez à utiliser une implémentation d'interface explicite à la place.


Je vais mettre à jour la question avec la prochaine erreur de construction pour la lisibilité



1
votes

Il vous dit que la contrainte: xxx

est redondant. Vous pouvez simplement supprimer class car locataire est plus contraint que class et inclut classe .


1 commentaires

Veuillez vérifier la question, mise à jour avec les résultats de la simple suppression de «classe» dans les listes de contraintes. Merci



2
votes

Il n'y a actuellement que trois classes héritables dans le cadre dont les descendants peuvent être des types de valeur: objet , valeur de type et Enum . Les trois de ces types sont des types de classe, mais tout type dérivé de valueltype ou Enum sera un type de valeur et tout type dérivé de objet Ce qui n'est pas dérivé de valeur type sera un type de classe. Avec tout type autre que ce qui précède, un classe ou struct serait soit redondant, soit contradictoire; non coïncidemment, c # désactive les contraintes d'être directement spécifiés pour les types ci-dessus.

Dans certaines langues et cadres, une philosophie de conception dominante est que s'il existe une forme d'expression particulière où le comportement qui s'applique à cette forme générale serait inutile Il n'y a aucune raison pour que le concepteur de langue / cadre ne soit pas démarré pour interdire une telle forme. Sous une telle philosophie, il serait parfaitement légal d'avoir un type générique contraint à un type scellé (E.G. Fnord) . Une telle chose serait inutile si le type en question était scellé et que non la version future ne serait jamais autrement , mais puisque l'application de l'interprétation normale des contraintes génériques à une telle situation donnerait un comportement raisonnable et, étant donné qu'il pourrait être éventuellement certaines situations dans lesquelles de telles contraintes pourraient être utiles (par exemple, un code d'écriture pour utiliser une classe qui est en développement et qu'il est actuellement scellé, mais peut être scellé ou non à être scellé dans sa version finale, ni de son code d'écriture pour interfacer avec le code basé sur la réflexion que s'attend à ce que les formes génériques particulières), la philosophie suggère que contraignant un type générique à une classe scellée devrait être légal.

Dans certaines autres langues et cadres, une philosophie différente détient: Si un programmeur peut s'attendre à une forme particulière. d'une construction pour offrir des fonctionnalités au-delà de la forme générale, mais ce n'est pas le cas, et si cette forme particulière ne semblerait pas très utile sans de telles fonctionnalités, la langue devrait interdire, même si la construction serait VE un sens précis qui a été bien défini et ne pouvait être exprimé par d'autres moyens si les responsables de la langue ne voient pas une raison pour que les programmeurs veulent exprimer ce sens réel.

Le fait que ni C # NOR .NET n'a aucun problème à avoir un paramètre de type contraint à un autre, même lorsque cet autre paramètre est d'un type qui ne serait pas accepté comme une contrainte, suggère que la restriction est imposée artificiellement par la langue en raison de la philosophie susmentionnée. Il est malheureux, IMHO, puisqu'il y a de nombreuses situations où il serait utile de pouvoir dire, par exemple xxx

et même si .NET permettrait u utilement à une telle construction, et Même si le seul obstacle qui empêche le C # d'excepter du code informatique à rechercher explicitement de telles contraintes afin de les interdire, les concepteurs C # ont décidé d'interdire de telles constructions plutôt que de leur permettre de se comporter comme ça. HasanyFlags ne pouvait rien faire directement avec un t qu'il ne pouvait pas faire avec system.enum , et à l'aide d'un t en tant que system.enum ne serait généralement pas plus rapide que d'utiliser un system.enum (parfois plus lent), mais t pourrait néanmoins être utile pour un Motifs de couple:

  1. La méthode pourrait appliquer au moment de la compilation que les paramètres doivent être le type * même * énuméré
  2. La méthode pourrait utiliser une classe statique `énumevaluator` pour générer et cacher des délégués statiques de type` Func`, de telle que `HasanyFlags (t Enum1, t Enum2)` pourrait être mis en œuvre comme `Retour Enumevaluator.hasanyFlags (Enum1, Enum2); `. Une telle fonction pourrait être plus de dix fois aussi rapide que `Enum.hasflag`.

    Néanmène, utile, car il pourrait être de spécifier de telles contraintes, le seul moyen de les spécifier dans C # est d'avoir le code source C # spécifiant un type factice pouvant être utilisé comme contrainte, puis exécutez le code compilé via un utilitaire qui remplacera toutes les références au type factice avec des références au type que on voulait utiliser en premier lieu.


0 commentaires