IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

problème fonction de généricité C#


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Par défaut problème fonction de généricité C#
    Bonjour,

    j'ai une question dont je n'arrive pas à trouver de réponse exacte.

    Ci-dessous vous trouverez une fonction template très simple, où elle prend un type T et fais la somme avec une autre variable sum de type T (théoriquement je devrais l'initialisé à 0).
    Le problème, c'est que si je sais que lors de l'appel à cette fonction le type T sera int ou double par exemple, le compilateur me dit que il ne peut pas faire la méthode += sur des type T, ce que je comprends, mais alors comment je fais pour ne pas avoir à écrire le même code pour double ou int ?? Faut-il que je convertisse input en double ou int avant ? (grâce à typeof)

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public T function<T>(T input)
    {
       T sum;
       sum += input;
    }

    Merci

    Algernon

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    je pense que tu vas devoir écrire une méthode par type, comme c'est le cas dans le framework pour les méthodes qu'on trouve dans system.math par exemple

    les expressions trees du fx4 peuvent être une solution, mais si ca reste plus compliqué à écrire qu'une méthode par type

    après ce n'est peut être pas nécessaire de gérer des types pour un méthode qui fait des calculs, si la méthode demande des doubles seulement, rien ne t'empeche de fournir des int et de convertir le retour
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Par défaut
    Malheureusement ca n'est pas possible.
    Lorsque tu fais ceci, le framework considère que T est un objet quelconque (donc un Object). Or l'opération + n'existe pas entre deux Object.
    Pour que ca soit possible, il faudrait éventuellement ajouter une contrainte sur T mais int et double n'ont que Object comme type commun (normal ce sont des types valeurs)

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Par défaut
    Bonjour et merci de vos réponses

    j'ai testé cette implémentation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public T function<T>(T input)
    {
        if (typeof(T) == typeof(int))
        {
            Object o = (object)input;
            int inputCastInt = (int)o;
            int sum += inputCastInt;
    }
    Ca fonctionne mais bon maintenant ça me fait faire deux boucle avec le même code pour les int et les double.

    Merci

    Algernon

  5. #5
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Par défaut
    Oui mais bon, autant faier ca directement dans ce cas là:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public int function(int input)
    {
        int sum += input;
    }
    D'ailleurs ta fonction ne retourne rien, c'est normal?

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Par défaut
    oui en fait j'aurais du retourné la valeur et c'est aussi vrai que utiliser un object "Object" puis caster ça en int c'est long et inutile, mais bon c'est que je m'intéresse aux templates et e voulais juste savoir si ça se faisais.

    Je vais évidement utiliser la méthode que tu as écrite

    Merci

    Algernon

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Algernon2 Voir le message
    Ci-dessous vous trouverez une fonction template très simple, où elle prend un type T et fais la somme avec une autre variable sum de type T (théoriquement je devrais l'initialisé à 0).
    Ce que tu as fait fonctionnerait avec les templates de C++, mais pas avec les génériques de .NET. Cela est dû à une différence fondamentale entre les templates et les génériques :

    - En C++, c'est le compilateur qui vérifie si le code d'un template est valide pour tous les paramètres de type que tu utilises, et le compile séparément pour chacun des paramètres de type. Dans le code compilé, le template n'existe plus : il a été remplacé par autant d'implémentations spécifiques que nécessaire.

    - En .NET, le compilateur génère un seul code pour la méthode générique : c'est à l'exécution que des types spécifiques sont créés en fonction des paramètres de type utilisés. Le type générique existe en tant que tel dans le code compilé, donc on ne sait pas à l'avance avec quels paramètres de type il sera utilisé : il faut donc que le code soit valable avec n'importe quel type (ou du moins n'importe quel type qui vérifie les contraintes, si tu spécifies des contraintes).

    (et en Java c'est encore un peu différent...)

    Puisqu'il n'existe pas de contrainte qui garantisse l'existence d'un opérateur +(T, T), le code n'est pas valable. Par contre, il y a une astuce qui consiste à générer les opérateurs dynamiquement en utilisant les expressions trees. Par exemple la classe suivante implémente les opérateurs + - * / :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    using System;
    using System.Linq.Expressions;
     
    ...
     
    public static class Operators<T>
    {
        private static readonly Func<T, T, T> _add;
        private static readonly Func<T, T, T> _subtract;
        private static readonly Func<T, T, T> _multiply;
        private static readonly Func<T, T, T> _divide;
     
        static Operators()
        {
            _add = CreateBinaryOperator(ExpressionType.Add);
            _subtract = CreateBinaryOperator(ExpressionType.Subtract);
            _multiply = CreateBinaryOperator(ExpressionType.Multiply);
            _divide = CreateBinaryOperator(ExpressionType.Divide);
        }
     
        private static Func<T, T, T> CreateBinaryOperator(ExpressionType expressionType)
        {
            var x = Expression.Parameter(typeof(T), "x");
            var y = Expression.Parameter(typeof(T), "y");
            var body = Expression.MakeBinary(expressionType, x, y);
            var expr = Expression.Lambda<Func<T, T, T>>(body, x, y);
            return expr.Compile();
        }
     
        public static T Add(T x, T y)
        {
            return _add(x, y);
        }
     
        public static T Subtract(T x, T y)
        {
            return _subtract(x, y);
        }
     
        public static T Multiply(T x, T y)
        {
            return _multiply(x, y);
        }
     
        public static T Divide(T x, T y)
        {
            return _divide(x, y);
        }
    }
    Tu peux l'utiliser comme ça :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // sum = sum + input
    sum = Operators<T>.Add(sum, input);
    Attention, ça ne fonctionnera pas avec tous les types : il faut que ces types supportent effectivement les opérateurs utilisés, sinon ça va planter à l'exécution.

    Le principe est expliqué plus en détails ici

Discussions similaires

  1. Problème : Fonctions et commande Execute
    Par bubi dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 15/11/2005, 11h01
  2. Problème fonction SDL
    Par seeme dans le forum SDL
    Réponses: 2
    Dernier message: 06/11/2005, 20h22
  3. Problème fonction PL/SQL
    Par SSJ17Vegeta dans le forum PL/SQL
    Réponses: 2
    Dernier message: 29/10/2005, 21h14
  4. Problème fonction et trigger sous 7.2
    Par anoukhan dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 22/06/2005, 22h53
  5. Réponses: 2
    Dernier message: 20/08/2004, 17h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo