簡體   English   中英

為擴展方法創建特定於硬件的委托

[英]Creating a hardware-specific delegate for an extension method

我正在為原始數值數組編寫擴展方法庫。 擴展方法有常規版本和硬件加速版本。 我正在嘗試使用委托,以便每個方法都有一個入口點。 例如,考慮一個對數組求和的簡單擴展方法:

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

}

這看起來非常丑陋、多余,並且違反了 DRY 原則。 這只是我正在實施的數十種方法中的一種,繼續這種當前模式將產生大量的ArrayExtensions類。

有沒有辦法解決這個不需要明確定義的問題? 或者更確切地說,有沒有辦法使這個通用,但僅限於支持的類型? 擴展方法僅適用於上述代碼中存在的類型。

您可以通過使用繼承來簡化這一點。 這將擺脫大部分。

作為額外的好處,虛擬呼叫比委托呼叫略快。 使用抽象基類而不是接口來增加性能。

這樣做的一個缺點是,您在選擇要使用的各個方法方面的靈活性較低。

作為替代方案,您可以考慮使用 T4 模板生成這個死記硬背的 C# 代碼。 它們很好地集成到 IDE 中。

另一種可能是反思。 這不會消除所有這些,但會消除一些。

您可以將您的方法聲明為:

        public static T Sum<T>(this T[] arry)
        {
            double sum = 0d;
            double dval = 0d;
            foreach (T val in arry)
            {
                if (double.TryParse(val.ToString(), out dval))
                {
                    try { sum += dval; }
                    catch (OverflowException) { break; }
                }
            }
            return (T)Convert.ChangeType(sum, typeof(T));
        }

或手動處理方法中的類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM