Question

Que puis-je faire si je veux une méthode générique qui accepte uniquement les types ayant surchargé un opérateur, par exemple l'opérateur de soustraction. J'ai essayé d'utiliser une interface comme contrainte, mais les interfaces ne peuvent pas avoir de surcharge d'opérateurs.

Quel est le meilleur moyen d'y parvenir?

Était-ce utile?

La solution

Il n'y a pas de réponse immédiate. les opérateurs sont statiques et ne peuvent pas être exprimés en contraintes - et les primitives existantes ne mettent en oeuvre aucune interface spécifique (contrairement à IComparable [< T >] qui peut être utilisé pour émuler une valeur supérieure à / inférieure -than).

Cependant; si vous voulez juste que cela fonctionne, alors, dans .NET 3.5, il y a quelques options ...

J'ai mis en place une bibliothèque ici qui permet de travailler efficacement et un accès simple aux opérateurs avec des génériques - tels que:

T result = Operator.Add(first, second); // implicit <T>; here

Il peut être téléchargé en tant que partie de MiscUtil

.

De plus, en C # 4.0, cela devient possible via dynamic:

static T Add<T>(T x, T y) {
    dynamic dx = x, dy = y;
    return dx + dy;
}

J'avais aussi (à un moment donné) une version .NET 2.0, mais celle-ci est moins testée. L’autre option consiste à créer une interface telle que

interface ICalc<T>
{
    T Add(T,T)() 
    T Subtract(T,T)()
} 

etc., mais vous devez ensuite passer un ICalc<T>; toutes les méthodes, ce qui devient compliqué.

Autres conseils

J'ai constaté que l'IL pouvait très bien gérer cela. Ex.

ldarg.0
ldarg.1
add
ret

Compilé dans une méthode générique, le code fonctionnera correctement tant qu'un type primitif est spécifié. Il peut être possible d’étendre cela aux fonctions d’opérateur appelées sur des types non primitifs.

Voir ici .

Il y a un morceau de code volé des internats que j'utilise beaucoup pour cela. Il recherche ou construit à l'aide de IL opérateurs arithmétiques de base. Tout cela est fait dans une classe générique Operation<T> et tout ce que vous avez à faire est d’affecter l’opération requise à un délégué. Comme add = Operation<double>.Add.

Il est utilisé comme ceci:

public struct MyPoint
{
    public readonly double x, y;
    public MyPoint(double x, double y) { this.x=x; this.y=y; }
    // User types must have defined operators
    public static MyPoint operator+(MyPoint a, MyPoint b)
    {
        return new MyPoint(a.x+b.x, a.y+b.y);
    }
}
class Program
{
    // Sample generic method using Operation<T>
    public static T DoubleIt<T>(T a)
    {
        Func<T, T, T> add=Operation<T>.Add;
        return add(a, a);
    }

    // Example of using generic math
    static void Main(string[] args)
    {
        var x=DoubleIt(1);              //add integers, x=2
        var y=DoubleIt(Math.PI);        //add doubles, y=6.2831853071795862
        MyPoint P=new MyPoint(x, y);
        var Q=DoubleIt(P);              //add user types, Q=(4.0,12.566370614359172)

        var s=DoubleIt("ABC");          //concatenate strings, s="ABCABC"
    }
}

<=> Le code source est une gracieuseté de paste bin: http://pastebin.com/nuqdeY8z

avec l'attribution ci-dessous:

/* Copyright (C) 2007  The Trustees of Indiana University
 *
 * Use, modification and distribution is subject to the Boost Software
 * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *  
 * Authors: Douglas Gregor
 *          Andrew Lumsdaine
 *          
 * Url:     http://www.osl.iu.edu/research/mpi.net/svn/
 *
 * This file provides the "Operations" class, which contains common
 * reduction operations such as addition and multiplication for any
 * type.
 *
 * This code was heavily influenced by Keith Farmer's
 *   Operator Overloading with Generics
 * at http://www.codeproject.com/csharp/genericoperators.asp
 *
 * All MPI related code removed by ja72. 
 */
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top