8
votes

C # Generics supporte les contraintes de signature type?

L'un des avantages avec des modèles C ++ est que vous (implicitement) peut nécessiter une certaine signature de type (E.G. Type T doit avoir une fonction X qui ne prend aucun paramètre et retourne un int). C # Generics supporte-t-il quelque chose de similaire?

Je suis au courant des contraintes basées sur la classe de base ou l'interface, mais ce n'est pas ce que je cherche.

(en tant que programmeur C ++ l'apprentissage C #, je me tromperais peut-être que ceci est une fonctionnalité que vous voudriez en C #. Toute commentaires sur cela serait également apprécié ...)


1 commentaires

Mais les contraintes d'interface sont déjà un moyen assez difficile d'exprimer quelque chose comme t implémente une méthode x () correspondant à une signature , ne pensez-vous pas?


7 Réponses :


0
votes

Il existe 5 types de contraintes que vous pouvez mettre sur des génériques dans .NET:

  1. Les contraintes de dérivation indiquent l'ascendance d'un paramètre de type.
  2. Les contraintes d'interface sont des interfaces implémentées par le paramètre de type.
  3. Les contraintes de type de valeur limitent un paramètre de type à une valeur de valeur.
  4. Les contraintes de type de référence limitent un paramètre de type à un type de référence.
  5. Les contraintes de constructeur stipulent que le paramètre de type a un constructeur sans défaut ou paramétré.

    Cette page affiche plus d'informations.


1 commentaires

"Je suis au courant des contraintes basées sur la classe de base ou l'interface, mais ce n'est pas ce que je cherche."



6
votes

Rien sauf pour les contraintes que vous avez déjà vues (qui font, pour être juste, couvrir de nombreux scénarios communs). Il y a quelques solutions de contournement communes:

  • dynamique , dans 4.0
  • Tapis de canard manuel à l'aide de la réflexion ou de la génération IL, etc.

    Aucun de ceux-ci n'a de vérification de type statique, etc., cependant.


3 commentaires

Dynamique est probablement le plus proche que je puisse obtenir. En fait, je pense souvent à des modèles C ++ comme une "langue dynamique de l'heure de la compilation" (ce qui est probablement une phrase qui n'a aucun sens pour personne, mais moi :)


@TOBIAS J'aurais allé avec "Début vérifié statique-Tapé"; p ( dynamique a des implications de l'exécution, mais je sais ce que vous voulez dire)


et tout à coup, ça a du sens pour tout le monde :)



4
votes

Oui, à travers une interface. Vous pouvez définir un objet générique qui a un type qui doit avoir une interface spécifique mise en œuvre. Dans cette interface, vous feriez essentiellement un objet ajouté à ce générique, la liste, par exemple, d'avoir une signature spécifique.

Que ce soit ou non ce que vous êtes pas à la recherche, c'est comme ça que vous l'accomplissez. :)


5 commentaires

Cela ne couvre toujours pas toutes les options, bien que - constructeurs avec des paramètres, des opérateurs, des méthodes statiques, etc.


@Marc Eh bien il n'y a pas une solution parfaite dans cette situation - comme vous l'avez noté dans votre réponse. L'OP va devoir faire plier un peu pour accomplir sa tâche. Et il n'a peut-être pas besoin d'aucune des choses que vous avez mentionnées. Il veut que sa classe générique soit conforme à "la fonction x qui ne prend aucun paramètre et retourne un int"


@MARC, je suis d'accord et soutenir les contraintes sur les constructeurs non par défaut serait bien IMHO. Les autres, pas tellement, surtout opérateurs :)


@Marc mais par tous les moyens, il s'agit simplement d'une solution en conserve. Il est plus que bienvenu pour attaquer cela de n'importe quel angle qui correspond à ses besoins :)


Cela nécessite le type de paramètre de type pour répondre aux besoins de la classe générique qui n'est parfois pas ce que vous voulez. (Je n'essaie pas de résoudre un problème particulier, mais essayant de comprendre quelles possibilités C # Generics fournit).



1
votes

non. C'est ce que interface s est pour. Créez une interface qui définit le contrat que vous souhaitez appliquer dans les contraintes de type. Puis spécifie que dans les contraintes.


0 commentaires

0
votes

Nope, non supporté en C #. Comme vous l'avez dit, la chose la plus proche nécessite que les classes impliquent une interface commune.

vous pourrait essayer d'imiter le comportement avec la réflexion, en recherchant la méthode par la signature, mais c'est une contrainte d'exécution et non une contrainte de compilation.


0 commentaires

0
votes

Non, c # n'a pas de contraintes comme ça.

Comme vous le savez, les contraintes génériques ne peuvent appliquer que l'héritage d'une classe de base ou d'une interface, ou quelques autres contraintes (contrainte de constructeur nouveau () , contrainte de type de référence classe , contrainte de type de valeur struct ).

Vous pourriez être capable d'atteindre votre comportement souhaité en utilisant délégués , et il existe de nombreux délégués génériques disponibles.
Par exemple, func est un délégué qui ne prend aucun paramètre et renvoie un int . Func prend une chaîne et DateTime et renvoie un int , etc ...


0 commentaires

3
votes

Non, ce n'est pas possible. Il est principalement causé par les différences entre les modèles C ++ et les génériques C #:

Lorsque vous compilez un modèle C ++, le code résultant a des types tels que vecteur et vecteur . Cela signifie que le compilateur doit connaître tous les paramètres de type possibles, mais cela signifie également qu'il peut les vérifier pour l'exactitude.

Lorsque vous compilez un type générique C #, vous créez un seul type générique: Liste . Pour cette raison, le compilateur C # n'a pas besoin de connaître tous les types possibles au type de compil, ce qui signifie que vous pouvez avoir des types génériques dans des bibliothèques binaires, ce qui n'est pas possible avec C ++. Mais cela signifie également que vous ne pouvez pas vérifier tous les types. Pour pouvoir faire quelque chose comme ça, il y a des contraintes, mais ils ne peuvent pas faire plusieurs choses que la vérification du temps de compilement C ++ peut, comme la vérification de la présence de certaines méthodes (sans utiliser d'interface ni de classe de base) ni de la présence d'opérateurs appropriés.

en C # 4, vous pouvez obtenir un effet quelque peu similaire à ce type de modèles utilisant dynamique , mais cela ne pas vérification du temps de compilation, ce qui signifie que vous perdez la sécurité - Vous pouvez mettre un type qui n'a pas les membres appropriés et vous ne le découvrirez pas avant d'atteindre cette ligne de code au moment de l'exécution.


0 commentaires