Что такое «базовый класс» для типов числовых значений в C #? - PullRequest
45 голосов
/ 06 мая 2009

Скажем, я хочу иметь метод, который принимает любое число, есть ли базовый класс (или какая-то другая концепция), которую я могу использовать?

Насколько я знаю, мне приходится делать перегрузки для всех различных числовых типов (Int32, Int16, Byte, UInt32, Double, Float, Decimal и т. Д.). Это кажется ужасно утомительным. Либо так, либо используйте тип «объект» и генерируйте исключения, если они не конвертируемы или не присваиваются двойному типу, что довольно плохо, так как не требует проверки времени компиляции.

UPDATE: Хорошо, спасибо за комментарии, вы правы, Пугало и Марк, фактически объявляя, что Double действительно работает для всех, кроме Decimal.

Итак, ответ, который я искал, - Double - он действует здесь как базовый класс, так как ему можно назначить большинство числовых типов. (Я полагаю, что десятичность не может быть назначена на Double, поскольку она может стать слишком большой.)

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;
}

Ответы [ 6 ]

23 голосов
/ 06 мая 2009

Ответ таков: вам не нужно предоставлять перегрузки для ВСЕХ числовых типов, только для Double и Decimal . Все остальные (за исключением, может быть, очень необычно больших) будут автоматически преобразованы в них.

Не базовый класс , но на самом деле это была красная сельдь. Базовый класс System.ValueType мало помогает, поскольку он включает типы, которые не являются числовыми. Во-первых, я запутался в ссылке на язык:)

(я просто искал, кому приписать ответ, и это была комбинация Пугало и Марка Гравелла, но так как они были комментариями, я разместил ответ здесь)

13 голосов
/ 06 мая 2009

Нет ни одного (или, по крайней мере, ни одного, который просто означает "числа"). Вы можете использовать:

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

Но это позволяет любой struct - не только числа. Если вы хотите сделать арифметику, универсальные операторы могут быть полезны. Кроме этого; перегружает его наиболее жизнеспособным вариантом.

10 голосов
/ 06 мая 2009

Краткий ответ: числовые типы являются типами значений, следовательно, они происходят от System.ValueType. Полный ответ: вы должны прочитать эту статью из MSDN . Более того, я думаю, что вы должны прочитать справочник по языку C # :). Тип значения не равен числовому типу, поскольку типы значений включают также структуры и перечисления.

7 голосов
/ 05 февраля 2018

Что я делаю:

 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...
 }

Теперь вы можете использовать его в методе:

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

или метод расширения

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

и в вашем коде:

 ...
 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

или, с методом расширения:

 Console.WriteLine(n.IsZero(5));  // false
 Console.WriteLine(n.IsZero(0f)); // true
 Console.WriteLine(n.IsZero("0")); // compiler error
5 голосов
/ 06 мая 2009

Базовый класс числовых типов: ValueType.

К сожалению, это все равно не поможет: DateTime, bool, Enum и сотни других типов также происходят от ValueType. В .NET нет базового класса NumericType.

0 голосов
/ 06 мая 2009

Здесь перегружены сигнатуры методов? Если вы хотите, чтобы ограниченная группа методов выполняла одну и ту же задачу, вы можете загрузить открытый метод и вызвать закрытый метод, который принимает любое число, путем преобразования входных данных в двойные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...