Generics - where is T - a number?

I'm trying to figure out a way to create a generic class for numeric types only, to do some calculations.

Is there a common interface for all types of numbers (int, double, float ...) that I miss?

If not, what would be the best way to create such a class?

UPDATE:

The main thing I'm trying to achieve is to check who is bigger between two variables of type T.

+41
generics c # numbers
Aug 12 '09 at 18:30
source share
8 answers

What version of .NET are you using? If you are using .NET 3.5, then I have an implementation of common operators in MiscUtil (free, etc.).

This method has methods like T Add<T>(T x, T y) and other arithmetic options for different types (for example, DateTime + TimeSpan ).

In addition, it works for all built-in, filmed, and custom-made statements and caches the delegate for execution.

Some additional information on why this is difficult is here .

You may also know that the dynamic (4.0) method also solves this problem indirectly - i.e.

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



In the comments to < / > - you really don't need operators; you just need to:

 T x = ..., T y = ... int c = Comparer<T>.Default.Compare(x,y); if(c < 0) { // x < y } else if (c > 0) { // x > y } 
+28
Aug 12 '09 at 20:02
source share

There are interfaces for some operations on number types, for example, IComparable<T> , IConvertible and IEquatable<T> . You can specify this to get specific functionality:

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

You can use delegates to extend the class with specific types of operations:

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

Using:

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

You can also store delegates in a class and have different factory methods that set delegates for a particular data type. Thus, type code is specific only to factory methods.

+12
Aug 12 '09 at 19:11
source share

You cannot do this, since you will have to use one interface for arithmetic operations. There have been many requests for Connect to add an IArithmetic interface for this particular purpose, but so far they have all been rejected.

You can sort the work around this by defining a structure without elements that implements the Calculator interface. We used this approach in a generic interpolation class in the Pluto Toolkit . For a detailed example, we have a β€œvector” calculator implementation here that allows our generic interpolator to work with vectors. There are similar ones for floats, doubles, quaternions, etc.

+8
Aug 12 '09 at 18:39
source share

The closest thing you get, I'm afraid. You will need to do more extensive type checking of numbers in the code.

 public class MyClass<T> where T : struct (...) 
+5
Aug 12 '09 at 18:36
source share

In Framework BCL (a base class library), many numerical functions (such as functions in System.Math) handle this by overloading each numerical type.

The static Math class in BCL contains static methods that you can call without creating an instance of the class. You can do the same in your class. For example, Math.Max ​​has 11 overloads:

 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
Aug 12 '09 at 18:43
source share
 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); } } } } 
+3
Sep 09 '13 at 23:23
source share

I do not believe that you can define this using a generic type constraint. Your code can internally check your requirements, perhaps using Double.Parse or Double.TryParse to determine if it is a number - or if VB.NET is out of the question, then you can use the IsNumeric () function.

Edit: You can add a link to Microsoft.VisualBasic.dll and call the IsNumeric () function from C #

+2
Aug 12 '09 at 18:39
source share

You cannot do this only at compile time. But you can add more restrictions to cut off most of the "bad types" to your number type, like below

yourclass <T> class, where T: IComparable, IFormattable, IConvertible, IComparabe <T>, IEquatable <T>, struct {... In the end, you still have to check at runtime if your type is valid using the object method. GetType ().

Compared only, IComparable <T> alone does the trick.

+2
Jul 01 2018-11-15T00:
source share



All Articles