How to convert numbers into generic type?

Advertisements

This is how I would like to be able to write my code. MethodB is just a dummy here, all we care about is that it’s returning type T.

public static class ClassA<T> where T: struct, INumber<T>
{
    public static T MethodA( T[][] matrix, T[] vector)
    {
        T result = T.Zero;
        int m = matrix.Length;
        for(int i = 0; i < m; i++)
        {
            result += MethodB( matrix[i], vector);
        }
        return result / ( m * 2 + 1);
    }

    public static T MethodB(T[] vector1, T[] vector2)
    {
        T result = T.One;
        return result;
    }
}

The problem is the return statement of MethodA. I run into CS0019. To fix this I would like to convert m into type T. I know that all T, which will ever be used, are going to be numbers which should allow for a constructor using m as a single argument. So I would like to have a way to convert m.

A workaround to my problem I found is:

public static class ClassA<T> where T: struct, INumber<T>
{
    public static T MethodA( T[][] matrix, T[] vector)
    {
        T result = T.Zero;
        int m = matrix.Length;
        for(int i = 0; i < m; i++)
        {
            result += MethodB( matrix[i], vector);
        }
        T convertedM = CreateT( m * 2 + 1);
        return result / convertedM;
    }

    public static T MethodB( T[] vector1, T[] vector2)
    {
        T result = T.One;
        return result;
    }

    public static T CreateT( int i)
    {
        T type = new T();
        if (type is double)
        {
            double d =(double) i;
            return (T)((object)d);
        }
        if (type is float)
        {
            float d =(float) i;
            return (T)((object)d);
        }
        //here would be a long list of different number types.
        throw new NotImplementedException();
    }        
}

This seems like a suboptimal solution to me though, since I have to check against all possible types. It feels like I am missing the obvious solution, like having an interface that makes sure int conversion is implemented for all T, but I don’t know how to do that. I would like to be able to add different number systems and use the oney given by the language.

What I tried:

  1. I looked through the documentation for INumbers, but couldn’t find anything usefull for this case.
  2. Then I found the work around and implemented it, so now it’s at least working.
  3. Afterwards I tried to write my own interface and implement it, but I couldn’t figure out how to implement the interface for something already given like doubles.

>Solution :

You can use one of the CreateChecked, CreateTruncating or CreateSaturating methods on the INumber<T> type.

For example:

return result / T.CreateChecked(m * 2 + 1);

CreateChecked: Creates an instance of the current type from a value, throwing an overflow exception for any values that fall outside the representable range of the current type.

CreateTruncating: Creates an instance of the current type from a value, truncating any values that fall outside the representable range of the current type.

CreateSaturating: Creates an instance of the current type from a value, saturating any values that fall outside the representable range of the current type.

Leave a ReplyCancel reply