72 votes

Génériques - où T est un nombre?

J'essaie de trouver un moyen de créer une classe générique pour les types de nombres uniquement, pour effectuer certains calculs.

Existe-t-il une interface commune pour tous les types de nombres (int, double, float ...) qui me manque ???

Si non, quel sera le meilleur moyen de créer une telle classe?

MISE À JOUR:

La principale chose que j'essaie de réaliser est de vérifier qui est le plus grand entre deux variables de type T.

35voto

Marc Gravell Points 482669

Quelle est la version de .NET vous aide? Si vous êtes en utilisant .NET 3.5, alors j'ai un générique opérateurs de mise en œuvre dans MiscUtil (libre, etc).

Cela a des méthodes comme T Add<T>(T x, T y),, et d'autres variantes de l'arithmétique sur les différents types (comme DateTime + TimeSpan).

En outre, cela fonctionne pour tous les encastrables, levée et sur mesure à des opérateurs, et des caches de la délégué pour la performance.

Quelques informations supplémentaires sur les raisons de cette délicate est ici.

Vous pouvez également savoir qu' dynamic (4.0) tri de la résout ce problème indirectement aussi - c'est à dire

dynamic x = ..., y = ...
dynamic result = x + y; // does what you expect


Re le commentaire à propos de < / > - vous n'avez pas réellement besoin d' opérateurs pour cela, il vous suffit:

T x = ..., T y = ...
int c = Comparer<T>.Default.Compare(x,y);
if(c < 0) {
    // x < y
} else if (c > 0) { 
    // x > y
}

15voto

Guffa Points 308133

Il existe des interfaces pour certains des opérations sur les types de nombre, comme l' IComparable<T>, IConvertible et IEquatable<T> interfaces. Vous pouvez spécifier que, pour obtenir une fonctionnalité spécifique:

public class MaxFinder<T> where T : IComparable<T> {

   public T FindMax(IEnumerable<T> items) {
      T result = default(T);
      bool first = true;
      foreach (T item in items) {
         if (first) {
            result = item;
            first = false;
         } else {
            if (item.CompareTo(result) > 0) {
               result = item;
            }
         }
      }
      return result;
   }

}

Vous pouvez utiliser les délégués à l'expansion d'une classe avec le type d'opérations spécifiques:

public class Adder<T> {

   public delegate T AddDelegate(T item1, T item2);

   public T AddAll(IEnumerable<T> items, AddDelegate add) {
      T result = default(T);
      foreach (T item in items) {
         result = add(result, item);
      }
      return result;
   }

}

Utilisation:

Adder<int> adder = new Adder<int>();
int[] list = { 1, 2, 3 };
int sum = adder.AddAll(list, delegate(int x, int y) { return x + y; });

Vous pouvez également stocker des délégués de la classe, et les différentes méthodes de fabrique qui met en place des délégués pour un type de données spécifique. De cette façon, le type de code spécifique est seulement dans les méthodes de fabrique.

11voto

Dag Points 1401

J'ai le plus peur de te voir le plus près de toi. Vous devrez faire des vérifications plus poussées pour les types de nombres dans le code.

 public class MyClass<T> where T : struct
(...)
 

9voto

Reed Copsey Points 315315

Vous ne pouvez pas le faire, puisque vous auriez à utiliser une interface unique pour les opérations arithmétiques. Il y a eu beaucoup de demandes sur Connecter pour ajouter un IArithmetic interface pour ce but précis, mais jusqu'à présent, ils ont tous été rejetés.

Vous pouvez sorte de contourner ce problème en définissant une structure avec pas de membres, qui met en œuvre un "Calculateur" de l'interface. Nous avons adopté cette approche dans une interpolation de classe générique dans le Pluton Toolkit. Pour un exemple détaillé, nous avons un "vecteur" de la calculatrice de mise en œuvre ici, ce qui permet à notre générique de l'interpolateur de travail avec les vecteurs. Il y a d'autres semblables pour les chars, les doubles, les quaternions, etc.

6voto

Robert Harvey Points 103562

Dans le Framework BCL (bibliothèque de classes de base), de nombreuses fonctions numériques (telles que celles de System.Math) gèrent cela en créant des surcharges pour chaque type numérique.

La classe statique Math dans la BCL contient des méthodes statiques, que vous pouvez appeler sans avoir à créer une instance de la classe. Vous pourriez faire la même chose en classe. Par exemple, Math.Max a 11 surcharges:

 public static byte Max(byte val1, byte val2);
public static decimal Max(decimal val1, decimal val2);
public static double Max(double val1, double val2);
public static short Max(short val1, short val2);
public static int Max(int val1, int val2);
public static long Max(long val1, long val2);
public static sbyte Max(sbyte val1, sbyte val2);
public static float Max(float val1, float val2);
public static ushort Max(ushort val1, ushort val2);
public static uint Max(uint val1, uint val2);
public static ulong Max(ulong val1, ulong val2);
 

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