Как упростить этот код, используя универсальные типы?

#c# #generics

#c# #дженерики

Вопрос:

 private delegate T MyFunc<T>(int i);

private static double SumNumber(int i, int n, MyFunc<double> func)
{
    double sum = 0.0;
    for (int j = i; i <= n; j  )
    {
        sum  = func(j);
    }
    return sum;
}

private static Vector SumVector(int i, int n, MyFunc<Vector> func)
{
    Vector sum = new Vector(0.0, 0.0);
    for (int j = i; i <= n; j  )
    {
        sum  = func(j);
    }
    return sum;
}
  

Это программа для вычисления суммы myFunc(j), где j — от i до n .

Я попытался использовать интерфейс, подобный:

 interface IAddable<T>
{
    static T operator  (T x, T y);
}
  

но это не сработало.

Итак, что мне делать?

Комментарии:

1. вы могли бы использовать Func вместо myFunc таким образом, вам не пришлось бы создавать делегат и использовать тот, который есть в .net

Ответ №1:

Во-первых, обратите внимание, что во многих отношениях нестандартная версия перегрузки проще. Универсальные типы не поддерживают ни операторы, ни интерфейсы.

Действительно, если Sum для ваших типов доступны методы (возможно, с помощью методов расширения IEnumerable<T> ), вызывающий может использовать просто:

 var data = sourceData.Select(projection).Sum();
  

где projection моральный эквивалент func .

Для того, чтобы сделать это по-своему, то, что вы могли бы попробовать в первую очередь, это dynamic :

 private static T Sum<T>(int i, int n, Func<int,T> func)
{
    if(i >= n) throw new ArgumentOutOfRangeException();
    T sum = func(i);
    for (int j = i   1; i <= n; j  )
    {
        sum = (dynamic)sum   (dynamic)func(j);
    }
    return sum;
}
  

в противном случае, есть некоторые хитрости, которые вы можете сделать, чтобы подделать универсальные операторы (см. MiscUtil ), или вы можете передать метод accumulator (т.Е. Func<T,T,T> add ) в качестве параметра.

Комментарии:

1. @Jon побил меня в поиске ссылки MiscUtil; p

2. Может ли объект dynamic типа быть неявно преобразован в объект типа T ? Я имею в виду, не следует ли вам написать это вместо : sum = (T)((dynamic)sum (dynamic)func(j));

3. @Nawaz dynamic может быть неявно преобразован во что угодно , но обратите внимание, что проверка выполняется во время выполнения; там есть большое предположение: что существует определенный оператор (T,T) , который возвращает T .

4. @MarcGravell: Я собирался опубликовать довольно похожий ответ, так что он у меня был готов 🙂

5. @Nawaz ваше (T) добавление тоже имеет смысл и, возможно, проясняет намерение; результат тот же, и я, конечно, не был бы против того, чтобы (T) там было больше.