Реализация метода Average в пользовательской оболочке Queue - PullRequest
0 голосов
/ 01 мая 2018

У меня есть пользовательский класс блокировки «Lockable», который оборачивает очередь. Однако отсутствует метод усреднения.

Это метод Average, который я пытался добавить в класс, указанный в ссылке на источник ниже

public float Average()
        {
            lock (syncLock)
            {
                return queue.Average();
            }
        }

но получите следующую ошибку в 'queue'

Очередь не содержит определения «Средний» и «лучший» Перегрузка расширения метода 'Enumerable.Average (IEnumerable)' требуется приемник типа 'IEnumerable'

Оригинальный источник https://gist.github.com/jaredjenkins/5421892

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

Ну, из источника похоже, что вы могли бы реализовать метод следующим образом:

        public double Average()
        {
            return (from item in CopyToArray() select MakeNumberOrThrow(item)).Average();
        }

        private int MakeNumberOrThrow(object mightBeANumber)
        {
            return (int) mightBeANumber;
        }

Как упомянуто в комментарии @Evk для использования LINQ Average (), тип должен быть числом. В C # нет способа ограничить универсальный тип числом, поэтому каким-то образом вы должны преобразовать тип в число. Очевидно, что этот или любые другие методы не будут безопасны для всех типов, которые могут быть в пользовательской оболочке очереди.

0 голосов
/ 02 мая 2018

Поскольку у вас явно есть какое-то поле или свойство, определенное в вашем классе, которое вы можете агрегировать для получения среднего значения, вы можете опционально определить лямбда-функцию выбора в конструкторе, которая будет использоваться для оценки во время выполнения. Единственное предостережение в том, что поле / свойство должно быть открыто видимым для чтения, поскольку оно определено внешне. Этот простой класс должен выполнить то, что вы пытаетесь сделать. Я заметил, что тип возврата по умолчанию для linq.Average () был double, а не float. Так что я изменил это, но в остальном оно должно быть адекватным.

public class QueueT<T>
{
    public QueueT(Func<T, int> avgSelector)
    {
        selector = avgSelector;
    }

    private Func<T, int> selector;
    private object syncLock = new object();
    private Queue<T> queue = new Queue<T>();

    public double Average()
    {
        lock (syncLock)
        {
            return (from item in queue select selector(item)).Average();
        }
    }

}

Тип образца

public class Car
{
   //
   public int HP => 500;
}

Затем, когда вы создаете экземпляр

public class RealImplementationandUseClass
{
    public RealImplementationandUseClass()
    {
        var q = new QueueT<Car>((c) => c.HP);
    }
}

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

...