47 votes

C# Ajout de deux valeurs génériques

Quelqu'un peut-il expliquer pourquoi cela ne fonctionnera pas? J'essayais de pouvoir ajouter deux valeurs quel que soit le type numérique.

 public static T Add<T> (T number1, T number2)
{
    return number1 + number2;
}

Lorsque je compile ceci, j'obtiens l'erreur suivante :

 Operator '+' cannot be applied to operands of type 'T' and 'T'

34voto

Adi Lester Points 10814

Les solutions données ici fonctionnent bien, mais j'ai pensé en ajouter une autre qui utilise des expressions

 public static T Add<T>(T a, T b)
{
    // Declare the parameters
    var paramA = Expression.Parameter(typeof(T), "a");
    var paramB = Expression.Parameter(typeof(T), "b");

    // Add the parameters together
    BinaryExpression body = Expression.Add(paramA, paramB);

    // Compile it
    Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();

    // Call it
    return add(a, b);
}

De cette façon, vous créez un Func<T, T, T> qui effectue l'addition. L'explication complète se trouve dans cet article .

13voto

rich.okelly Points 24144

Le type T n'est pas connu par le compilateur, il ne peut donc pas trouver un opérateur + surchargé défini n'importe où...

Le mieux que vous puissiez faire actuellement est de déclarer votre méthode en tant que telle (puisque tous les types numériques sont convertibles en double) :

 public static double Add (double number1, double number2)
{
  return number1 + number2;
}

ou si vous êtes sûr qu'un opérateur + approprié sera défini :

 public static T Add<T>(T number1, T number2)
{
  dynamic dynamic1 = number1;
  dynamic dynamic2 = number2;
  return dynamic1 + dynamic2;
}

Mis à jour

ou une combinaison des deux :

 public static T Add<T>(T in1, T in2)
{
    var d1 = Convert.ToDouble(in1);
    var d2 = Convert.ToDouble(in2);
    return (T)(dynamic)(d1 + d2);
}

4voto

user5931 Points 11

Comme il s'agit d'un type générique sans contrainte, le compilateur ne sait pas si les types impliqués auront '+' surchargés, d'où l'erreur du compilateur.

Voici quelques solutions de contournement :

 public static TResult Add<T1, T2, TResult>(T1 left, T2 right, Func<T1, T2, TResult> AddMethod)
{
    return AddMethod(left, right);
}

var finalLabel = Add("something", 3,(a,b) => a + b.ToString());

Le code ci-dessous vous permet de construire mais il est évalué au moment de l'exécution, donc pas sûr à l'exécution

 public static T AddExpression<T>(T left, T right)
{
    ParameterExpression leftOperand = Expression.Parameter(typeof(T), "left");
    ParameterExpression rightOperand = Expression.Parameter(typeof(T), "right");
    BinaryExpression body = Expression.Add(leftOperand, rightOperand);
    Expression<Func<T, T, T>> adder = Expression.Lambda<Func<T, T, T>>(
        body, leftOperand, rightOperand);
    Func<T, T, T> theDelegate = adder.Compile();
    return theDelegate(left, right);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X