Я пишу библиотеку методов расширения для примитивных числовых массивов. Методы расширения имеют как обычную, так и аппаратную версию. Я пытаюсь использовать делегатов, чтобы у меня была одна точка входа для каждого метода. Например, рассмотрим простой метод расширения, который суммирует массив:
public static class ArrayExtensions
{
#region Data Members
private delegate TResult SumArrayDelegate<in TIn, out TResult>( TIn[] array );
private static SumArrayDelegate<sbyte,int> SumArraySByte_;
private static SumArrayDelegate<byte,int> SumArrayByte_;
private static SumArrayDelegate<short,int> SumArrayShort_;
private static SumArrayDelegate<ushort,int> SumArrayUShort_;
private static SumArrayDelegate<int,int> SumArrayInt32_;
private static SumArrayDelegate<uint,uint> SumArrayUInt32_;
private static SumArrayDelegate<long,long> SumArrayInt64_;
private static SumArrayDelegate<ulong,ulong> SumArrayUInt64_;
private static SumArrayDelegate<float,float> SumArrayFloat_;
private static SumArrayDelegate<double,double> SumArrayDouble_;
#endregion
#region Constructor
static ArrayExtensions()
{
if( Avx2.IsSupported )
{
SumArraySByte_ = Avx2Utilities.Sum;
SumArrayByte_ = Avx2Utilities.Sum;
SumArrayShort_ = Avx2Utilities.Sum;
SumArrayUShort_ = Avx2Utilities.Sum;
SumArrayInt32_ = Avx2Utilities.Sum;
SumArrayUInt32_ = Avx2Utilities.Sum;
SumArrayInt64_ = Avx2Utilities.Sum;
SumArrayUInt64_ = Avx2Utilities.Sum;
SumArrayFloat_ = Avx2Utilities.Sum;
SumArrayDouble_ = Avx2Utilities.Sum;
}
else if( Avx.IsSupported )
{
SumArraySByte_ = AvxUtilities.Sum;
SumArrayByte_ = AvxUtilities.Sum;
SumArrayShort_ = AvxUtilities.Sum;
SumArrayUShort_ = AvxUtilities.Sum;
SumArrayInt32_ = AvxUtilities.Sum;
SumArrayUInt32_ = AvxUtilities.Sum;
SumArrayInt64_ = AvxUtilities.Sum;
SumArrayUInt64_ = AvxUtilities.Sum;
SumArrayFloat_ = AvxUtilities.Sum;
SumArrayDouble_ = AvxUtilities.Sum;
}
else
{
SumArraySByte_ = ArrayUtilities.Sum;
SumArrayByte_ = ArrayUtilities.Sum;
SumArrayShort_ = ArrayUtilities.Sum;
SumArrayUShort_ = ArrayUtilities.Sum;
SumArrayInt32_ = ArrayUtilities.Sum;
SumArrayUInt32_ = ArrayUtilities.Sum;
SumArrayInt64_ = ArrayUtilities.Sum;
SumArrayUInt64_ = ArrayUtilities.Sum;
SumArrayFloat_ = ArrayUtilities.Sum;
SumArrayDouble_ = ArrayUtilities.Sum;
}
}
#endregion
public static int Sum( this sbyte[] array ) => SumArraySByte_( array );
public static int Sum( this byte[] array ) => SumArrayByte_( array );
public static int Sum( this short[] array ) => SumArrayShort_( array );
public static int Sum( this ushort[] array ) => SumArrayUShort_( array );
public static int Sum( this int[] array ) => SumArrayInt32_( array );
public static uint Sum( this uint[] array ) => SumArrayUInt32_( array );
public static long Sum( this long[] array ) => SumArrayInt64_( array );
public static ulong Sum( this ulong[] array ) => SumArrayUInt64_( array );
public static float Sum( this float[] array ) => SumArrayFloat_( array );
public static double Sum( this double[] array ) => SumArrayDouble_( array );
}
Это кажется невероятно уродливым, избыточным и нарушающим принципы СУХОГО. Это только один из десятков методов, которые я реализую, и продолжение этого текущего шаблона приведет к массивному классу ArrayExtensions
.
Есть ли способ приблизиться к этому, который не потребует явных определений? Или, скорее, есть способ сделать это универсальным, но ограниченным только поддерживаемыми типами? Методы расширения будут доступны только для типов, представленных в приведенном выше коде.