web-dev-qa-db-fra.com

Quelle est la "classe de base" pour les types de valeur numérique C #?

Disons que je veux avoir une méthode qui prend n'importe quel nombre, y a-t-il une classe de base (ou un autre concept) que je peux utiliser? 

Autant que je sache, je dois créer des surcharges pour tous les types numériques différents (Int32, Int16, Byte, UInt32, Double, Float, Decimal, etc.). Cela semble terriblement fastidieux. Soit ça, soit utilisez le type "objet" et lâchez des exceptions si elles ne sont pas convertibles ou assignables à un double - ce qui est assez grave car cela signifie qu'il n'y a pas de vérification de la compilation.

UPDATE: .__ OK, merci pour les commentaires, vous avez raison Scarecrow et Marc, le déclarer comme Double fonctionne en fait pour tous sauf Decimal. 

La réponse que je cherchais est donc Double. Elle agit ici comme une classe de base car la plupart des types numériques lui sont assignables. (Je suppose que Decimal n'est pas assignable à Double, car il pourrait devenir trop gros.)

public void TestFormatDollars() {
    int i = 5;
    string str = FormatDollars(i);   // this is OK
    byte b = 5;
    str = FormatDollars(b);     // this is OK
    decimal d = 5;
    str = FormatDollars(d);     // this does not compile - decimal is not assignable to double
}

public static string FormatDollars(double num) {
    return "$" + num;
}
43
mike nelson

La réponse est: vous n’avez pas besoin de fournir des surcharges pour TOUS les types numériques, mais seulement pour Double et Décimal . Toutes les autres (à l'exception peut-être de très grandes tailles) seront automatiquement converties en celles-ci. 

Pas une classe base mais en fait c'était le hareng rouge. La classe de base System.ValueType n'aide pas beaucoup car elle inclut des types qui ne sont pas numériques. La référence linguistique que je lisais est ce qui m'a le plus troublé :)

(Je cherchais simplement à qui attribuer la réponse et c'était une combinaison de Scarecrow et de Marc Gravell, mais comme il s'agissait de commentaires, j'ai mis la réponse ici)

20
mike nelson

Il n'y en a pas un (ou du moins, pas un qui juste signifie "nombres"). Vous pouvez utiliser:

void Foo<T>(T value) where T : struct {...}

Mais cela permet toute structure - pas seulement des nombres. Si vous voulez faire de l'arithmétique, les opérateurs génériques peuvent être utiles. Autre que ça; la surcharge l'option la plus viable.

13
Marc Gravell

La réponse courte est: Les types numériques sont des types de valeur, ils dérivent donc de System.ValueType. La réponse complète est: vous devriez lire cet article de MSDN . De plus, je pense que vous devriez lire la référence du langage C # :). Le type de valeur n'est pas égal au type numérique, car les types de valeur incluent également les structures et les énumérations. 

10
Dmitry Lobanov

Ce que je fais:

 public interface INumeric<T>
 {
     T Zero { get; }
     T One { get; }
     T MaxValue { get; }
     T MinValue { get; }
     T Add(T a, T b);
     // T Substract(....
     // T Mult...
 }  

 public struct Numeric: 
     INumeric<int>, 
     INumeric<float>,
     INumeric<byte>,
     INumeric<decimal>,
     // INumeric<other types>
 {
     int INumeric<int>.Zero => 0;
     int INumeric<int>.One => 1;
     int INumeric<int>.MinValue => int.MinValue;
     int INumeric<int>.MaxValue => int.MaxValue;
     int INumeric<int>.Add(int x, int y) => x + y;

     // other implementations...
 }

Maintenant, vous pouvez l'utiliser dans une méthode:

bool IsZero<TNum, T>(TNum ops, T number) 
   where TNum : INumeric<T>
{
   return number == ops.Zero;      
}

ou méthode d'extension

 public static bool IsZero<TNum, T>(this TNum ops, T number)
      where TNum : INumeric<T>
 {
      return number == ops.Zero;
 }

et dans votre code:

 ...
 var n = new Numeric(); // can be an static prop

 Console.WriteLine(IsZero(n, 5)); // false
 Console.WriteLine(IsZero(n, 0f)); // true
 Console.WriteLine(IsZero(n, "0")); // compiler error

ou, avec méthode d'extension: 

 Console.WriteLine(n.IsZero(5));  // false
 Console.WriteLine(n.IsZero(0f)); // true
 Console.WriteLine(n.IsZero("0")); // compiler error
7
Luis

La classe de base des types numériques est ValueType .

Malheureusement, cela ne vous aidera toujours pas: DateTime, bool, Enum et des centaines d'autres types dérivent également de ValueType. Il n'y a pas de classe de base NumericType dans .NET.

5
LukeH

Les signatures de méthodes surchargées sont-elles hors de question ici? 

0
Greg B