Дженерики - где T является числом? [дубликат]

Если Вы хотите безопасность типов классов, с удобством синтаксиса перечисления и разрядной проверки, рассматриваете Безопасные Маркировки в C++ . Я работал с автором, и он довольно умен.

Остерегаются, все же. В конце этот пакет использует шаблоны и макросы!

59
задан CD.. 3 September 2009 в 18:24
поделиться

6 ответов

Какую версию .NET вы используете? Если вы используете .NET 3.5, то у меня есть реализация общих операторов в MiscUtil (бесплатно и т. Д.).

Здесь есть такие методы, как T Add ( T x, T y) и другие варианты арифметики для различных типов (например, DateTime + TimeSpan ).

Кроме того, это работает для всех встроенных, расширенных и заказных операторов и кешей делегат для производительности.

Некоторые дополнительные сведения о том, почему это сложно, можно найти здесь .

Вы также можете узнать, что сортировка dynamic (4.0) решает эту проблему проблема также косвенно - например,

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

Re комментарий о < / > - вам на самом деле не нужны операторы для этого; вам просто нужно:

T x = ..., T y = ...
int c = Comparer<T>.Default.Compare(x,y);
if(c < 0) {
    // x < y
} else if (c > 0) { 
    // x > y
}
30
ответ дан 24 November 2019 в 18:31
поделиться

Боюсь, что ближе всего к вам будет структура. Вам придется провести более тщательную проверку числовых типов в коде.

public class MyClass<T> where T : struct
(...)
9
ответ дан 24 November 2019 в 18:31
поделиться

Вы не можете этого сделать, поскольку вам придется использовать один интерфейс для арифметических операций. В Connect было много запросов на добавление интерфейса IArithmetic для этой конкретной цели, но пока все они были отклонены.

Вы можете как бы обойти это, определив структуру без членов, которая реализует «Калькулятор» "интерфейс. Мы использовали этот подход в универсальном классе интерполяции в Pluto Toolkit . В качестве подробного примера у нас есть реализация «векторного» калькулятора здесь , которая позволяет нашему универсальному интерполятору работать с векторами. Есть аналогичные для поплавков, двойников, кватернионов и т. Д.

8
ответ дан 24 November 2019 в 18:31
поделиться

Существуют интерфейсы для некоторых операций с числовыми типами, например IComparable , IConvertible и IEquatable интерфейсов. Вы можете указать это для получения определенной функциональности:

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

}

Вы можете использовать делегаты для расширения класса с помощью операций, зависящих от типа:

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

}

Использование:

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

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

15
ответ дан 24 November 2019 в 18:31
поделиться

В Framework BCL (библиотека базовых классов) многие числовые функции (например, функции в System.Math) решают эту проблему, имея перегрузки для каждого числового типа.

Статическая математика Класс в BCL содержит статические методы, которые можно вызывать без необходимости создавать экземпляр класса. Вы могли бы сделать то же самое в своем классе. Например, Math.Max ​​имеет 11 перегрузок:

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);
4
ответ дан 24 November 2019 в 18:31
поделиться

Я не верю, что вы можете определить это, используя ограничение универсального типа. Ваш код может внутренне проверять ваши требования, возможно, используя Double.Parse или Double.

2
ответ дан 24 November 2019 в 18:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: