在 C# 中混合动态和泛型

Mixing Dynamics and Generics in C#

我正在用 C# 编写函数。我的函数需要根据值的类型确定一组值的范围。我将来会支持更多类型,这就是为什么我想要一个通用函数。现在,我只考虑 Int32DateTime。目前,我有以下内容:

private void GetRange<T>(List<Value> list, out dynamic absoluteMin, out dynamic absoluteMax, out dynamic begin, out dynamic mean out dynamic finish)
{
  T tempMin = default(T);
  T tempMax = default(T);

  begin = tempMin;
  if (tempMin is Int32) 
  {
    absoluteMin = Int32.MinValue;
    begin = Int32.MinValue;
    finish = Int32.MaxValue;
    absoluteMax = Int32.MaxValue;
  }
  else if (tempMin is DateTime)
  {
    absoluteMin = DateTime.MinValue;
    begin = new DateTime(2000, 1, 1);
    end = DateTime.Today;
    absoluteMax = DateTime.MaxValue;
  }

  foreach (var item in list)
  {
    var value = item.Value;
    if (tempMin is DateTime)
    {
      // ...
    }
    // determine begin and end of values in the list
  }
}

我这样调用这个方法:

dynamic min = null;
dynamic max = null;
dynamic start = null;
dynamic end = null;

var useInt = ShouldIUseInt();
if (useInt)
  GetRange<Int32>(myList, min, max, start, end);
else
  GetRange<DateTime>(myList, min, max, start, end);

调用该方法时,它会抛出一个运行时错误,内容如下:

The best overloaded method match for 'myClass.GetRange<System.DateTime>
(System.Collections.Generic.List<Value>, out object, out object, out object, out object)' 
has some invalid arguments

我不明白为什么会出现此运行时错误或如何修复它。任何帮助表示赞赏。谢谢。

您真的不想走这条将不同用途组合到单一功能中的路线。更好的方法是从您的结果中创建一个通用的,然后创建一个扩展程序 class 来聚合您的结果。

using System.Linq;

public class Range<T>
{
   public T Min { get; private set; }
   public T Max { get; private set; }

   public Range(T min, T max) 
   {
      Min = min;
      Max = max;
   }
}

public static class RangeExtensions
{
    public static Range<T> GetRange<T>(this List<T> values)
    {
        return new Range<T>(values.Min(), values.Max());
    }
}

您可以在任何包含可比较的基本类型和实现 IComparable<T> 的类型的列表上调用它,如下所示:

 List<int> intList = new List<int> { 1, 2, 3, 4, 5 };
 List<DateTime> dateList = new List<DateTime> { DateTime.Now, DateTime.Now.AddDays(3), DateTime.Now.AddDays(5) };

 var intRange = intList.GetRange ();
 var dateRange = dateList.GetRange ();