Вопрос по c#, numbers, generics – Дженерики - где Т это число? [Дубликат]

50

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

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

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

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

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

ОБНОВИТЬ:

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

(ответил на комментарий) Marc Gravell
Вы пробовали IConvertible / IComparible? - Все классы чисел поддерживают это. BrainSlugs83
Проверьте этот пост здесьstackoverflow.com/questions/32664/... David
Они неработать в этом сценарии, но когда выработа с Generics этохорошо знатьограничения общего типа ".msdn.microsoft.com/en-us/library/d5x73970%28VS.80%29.aspx STW

Ваш Ответ

8   ответов
2

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

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

8

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

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

это неработающая ссылка! happygilmore
8

Придется сделать более обширные проверки для типов чисел в коде.

public class MyClass<t> where T : struct
(...)
</t>
почему бы и нетwhere T: struct, IConvertible, тот'немного ближе, по крайней мере. BrainSlugs83
29

то у меня естьреализация универсальных операторов в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
}
</t>
я использую .NET 3.5, я пытался сделатьесли (х> у)» в то время как х и у типа Т. CD..
У MiscUtil есть Operator.GreaterThan, но вы неэто даже нужно; будет обновляться, чтобы показать, почему нет ... Marc Gravell
4

В Framework BCL (библиотеке базовых классов) многие числовые функции (например, функции в 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);
3
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

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

        public Del GetMethodInt(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 deleg = null;
            switch (ch)
            {
                case 1:
                    deleg = c.Addition;
                    result = deleg.Invoke(numone, numtwo);
                    break;
                case 2: deleg = c.Substraction;
                    result = deleg.Invoke(numone, numtwo);
                    break;
                case 3: deleg = c.Division;
                    result = deleg.Invoke(numone, numtwo);
                    break;
                case 4: deleg = c.Multiplication;
                    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(ch);
            }
            else
            {
                cs.GetMethodInt(ch);
            }

        }
    }
}
15

например,IComparableIConvertible а также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;
   }

}
</t></t></t>

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

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

}
</t></t>

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

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

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

2

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

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

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

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