Как сделать универсальный метод усреднения, чтобы в него можно было вставить любой тип? - PullRequest
0 голосов
/ 18 октября 2019

Пытаюсь сделать Общий метод среднего. Так что метод может взаимодействовать с любым типом. Но также значения любого типа должны быть общими. так что вы можете иметь типы: int, float, decimal.

Я пробую это так:

public class Calculator<T>
    {
        public T Average(List<T>items, Func<T, T>  getValue )
        {

            T sum = 0 ;

            foreach (var item in items)
            {
                sum += getValue(item);
            }

            return (T) Convert.ChangeType(sum / items.Count(), typeof(T));
        }
    }
}

И у меня есть пример класса, подобный этому:

public  class Product<T>
    {

        public T Weight { get; set; }

    }

Но я уже получаю сообщение об ошибке:

   T sum = 0 ;

Невозможно неявно преобразовать тип 'int' в 'T'

и класс Program. :


            var listProducts = new List<Product<int>> { 
                    new Product<int>{ Weight = 1},
                    new Product<int> { Weight = 2},
                    new Product<int> { Weight = 87}
            };
            var calc2 = new Calculator<Product<int>>();
            var averageWeight = calc2.Average(listProducts, p => p.Weight);

            Console.WriteLine($"Average weight is: {averageWeight}" );

У меня теперь так:

public class Calculator<T> where T: class
    {
        public T Average(List<T>items, Func<T, T>  getValue )
        {

            T sum = default(T);

            foreach (var item in items)
            {
                sum += getValue(item);
            }

            return (sum / items.Count());
        }
    }

Но я получаю эту ошибку:

'+=' cannot be applied to operands of type 'T' and 'T'

В этой строке:

sum += getValue(item);

1 Ответ

2 голосов
/ 18 октября 2019

Попробуйте использовать

T sum = default(T);

Также имеет смысл ограничение общего типа, если вы используете только типы значений, например,

where T : struct

Кроме того, вы передали p => p.Weight как Func<T, T> getValue, это неверно, вы должны объявить дополнительный универсальный параметр для возвращаемого значения для Func, в настоящее время вы принимаете и возвращаете тот же тип

Наконец, я заставляю ваш фрагмент работать, добавляя дополнительныйуниверсальный параметр и сделав sum как dynamic

    public class Program
    {
        static void Main(string[] args)
        {
            var listProducts = new List<Product<int>> {
                new Product<int>{ Weight = 1},
                new Product<int> { Weight = 2},
                new Product<int> { Weight = 87}
            };
            var calc2 = new Calculator<Product<int>, int>();
            var averageWeight = calc2.Average(listProducts, p => p.Weight);

            Console.WriteLine($"Average weight is: {averageWeight}");
        }
    }

    public class Calculator<T, S> where S : struct
    {
        public S Average(List<T> items, Func<T, S> getValue)
        {
            dynamic sum = default(S);

            foreach (var item in items)
            {
                var result= getValue(item);
                sum += result;
            }

            return (S)Convert.ChangeType(sum / items.Count, typeof(S));
        }
    }

В вашем фрагменте Product<int> в качестве параметра универсального типа для Calculator и int является параметром универсального типа для Product,T>, вы можете 'использовать оба из них как один параметр в getValue и возвращать обратно из Average

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...