Generics - где T это число? [Дубликат]

На этот вопрос уже есть ответ:

Есть ли ограничение, ограничивающее мой универсальный метод числовыми типами? 20 ответов

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

Есть ли общий интерфейс для всех типов чисел (int, double, float ...), которые мне не хватает ???

Если нет, как лучше создать такой класс?

ОБНОВИТЬ

Главное, чего я пытаюсь добиться - это проверить, кто больше между двумя переменными типа T.

 Fredrik Mörk12 авг. 2009 г., 20:33
 David12 авг. 2009 г., 20:33
Проверьте этот пост здесь / Stackoverflow.com вопросы / 32664 / ...
 STW12 авг. 2009 г., 20:56
Они не работают в этом сценарии, но когда вы работаете с Generics, полезно знать об «ограничениях универсального типа». Msdn.microsoft.com / EN-US / библиотека / d5x73970% 28VS.80% 29.aspx
 Marc Gravell♦12 авг. 2009 г., 22:16
(ответил на комментарий)
 BrainSlugs8329 авг. 2014 г., 08:57
Вы пробовали IConvertible / IComparible? - Все классы чисел поддерживают это.

Ответы на вопрос(8)

ты получаешь это @ структура Вы должны будете сделать более обширные проверки для типов чисел в коде.

public class MyClass<T> where T : struct
(...)
 BrainSlugs8329 авг. 2014 г., 08:55
почему бы нетwhere T: struct, IConvertible, это как минимум немного ближе.

например, функции в System.Math) справляются с этим, имея перегрузки для каждого числового типа.

Статический класс 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);
Решение Вопроса

то у меня есть реализация универсальных операторов в MiscUtil (бесплатно и т. д.).

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

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

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

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

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

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

T x = ..., T y = ...
int c = Comparer<T>.Default.Compare(x,y);
if(c < 0) {
    // x < y
} else if (c > 0) { 
    // x > y
}
 Marc Gravell♦12 авг. 2009 г., 22:12
MiscUtil имеет Operator.GreaterThan, но вам это даже не нужно; будет обновляться, чтобы показать, почему нет ...
 CD..12 авг. 2009 г., 22:09
Я использую .NET 3.5, я пытался сделать "if (x> y)", пока x и y типа T.

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

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

 happygilmore30 дек. 2013 г., 23:28
это неработающая ссылка!

что вы можете определить это, используя ограничение общего типа. Ваш код может внутренне проверить ваши требования, возможно, используя Double.Parse или Double.TryParse, чтобы определить, является ли это число - или если о VB.NET не может быть и речи, тогда вы можете использовать функцию IsNumeric ().

Редактировать Вы можете добавить ссылку на Microsoft.VisualBasic.dll и вызвать функцию IsNumeric () из c #

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GenericPratice1
{
    public delegate T Del<T>(T numone, T numtwo)where T:struct;
    class Class1
    {
        public T Addition<T>(T numone, T numtwo) where T:struct
        {
            return ((dynamic)numone + (dynamic)numtwo);
        }
        public T Substraction<T>(T numone, T numtwo) where T : struct
        {
            return ((dynamic)numone - (dynamic)numtwo);
        }
        public T Division<T>(T numone, T numtwo) where T : struct
        {
            return ((dynamic)numone / (dynamic)numtwo);
        }
        public T Multiplication<T>(T numone, T numtwo) where T : struct
        {
            return ((dynamic)numone * (dynamic)numtwo);
        }

        public Del<T> GetMethodInt<T>(int ch)  where T:struct
        {
            Console.WriteLine("Enter the NumberOne::");
            T numone =(T) Convert.ChangeType((object)(Console.ReadLine()), typeof(T));
            Console.WriteLine("Enter the NumberTwo::");
            T numtwo = (T)Convert.ChangeType((object)(Console.ReadLine()), typeof(T));
            T result = default(T);
            Class1 c = this;
            Del<T> deleg = null;
            switch (ch)
            {
                case 1:
                    deleg = c.Addition<T>;
                    result = deleg.Invoke(numone, numtwo);
                    break;
                case 2: deleg = c.Substraction<T>;
                    result = deleg.Invoke(numone, numtwo);
                    break;
                case 3: deleg = c.Division<T>;
                    result = deleg.Invoke(numone, numtwo);
                    break;
                case 4: deleg = c.Multiplication<T>;
                    result = deleg.Invoke(numone, numtwo);
                    break;
                default:
                    Console.WriteLine("Invalid entry");
                    break;
            }
            Console.WriteLine("Result is:: " + result);
            return deleg;
        }

    }
    class Calculator
    {
        public static void Main(string[] args)
        {
            Class1 cs = new Class1();
            Console.WriteLine("Enter the DataType choice:");
            Console.WriteLine("1 : Int\n2 : Float");
            int sel = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("Enter the choice::");
            Console.WriteLine("1 : Addition\n2 : Substraction\3 : Division\4 : Multiplication");
            int ch = Convert.ToInt32(Console.ReadLine());
            if (sel == 1)
            {
                cs.GetMethodInt<int>(ch);
            }
            else
            {
                cs.GetMethodInt<float>(ch);
            }

        }
    }
}

например,IComparable<T>, IConvertible а такжеIEquatable<T> интерфейсы. Вы можете указать это, чтобы получить определенную функциональность:

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

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

жить больше ограничений, чтобы отсеять большинство «плохих типов» для вашего числового типа, как показано ниже

class yourclass <T>, где T: IComparable, IFormattable, IConvertible, IComparabe <T>, IEquatable <T>, struct {... В конце концов, вам все равно придется проверять во время выполнения, является ли ваш тип приемлемым с использованием object.GetType () метод.

Если только сравнение, тогда IComparable <T> делает свое дело.

Ваш ответ на вопрос