Добавление методов в расширения - PullRequest
0 голосов
/ 27 апреля 2018

Я нашел некоторый код для Queue фиксированного размера здесь . Сейчас я пытаюсь добавить к этому Average метод, но получаю сообщение:

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

Для нормального Queue я могу использовать метод Average. Почему я не могу получить доступ к этому здесь?

Также сначала не работает преобразование в массив или список, а затем взятие среднего: queue.ToArray().Average().

Наконец, почему лучше обернуть это расширение в новый класс, а не наследовать от Queue, выполнив public class FixedSizeQueue<T> : Queue<T>?

public class FixedSizeQueue<T>
{
    private Queue<T> queue;

    public FixedSizeQueue(int capacity)
    {
        Capacity = capacity;
        queue = new Queue<T>(capacity);
    }

    public int Capacity { get; private set; }

    public int Count { get { return queue.Count; } }

    public T Average()
    {
        return queue.Average();
    }

    public void Clear()
    {
        queue.Clear();
    }

    public T ElementAt(int i)
    {
        return queue.ElementAt(i);
    }

    public T Enqueue(T item)
    {
        queue.Enqueue(item);
        if (queue.Count > Capacity)
        {
            return queue.Dequeue();
        }
        else
        {
            //if you want this to do something else, such as return the `peek` value
            //modify as desired.
            return default(T);
        }
    }

    public T Peek()
    {
        return queue.Peek();
    }

    // Got it from somewhere, don't know where.
    public IEnumerator<T> GetEnumerator()
    {
        return ((IEnumerable<T>)queue).GetEnumerator();
    }

    //IEnumerator IEnumerable.GetEnumerator()
    //{
    //    return ((IEnumerable<T>)queue).GetEnumerator();
    //}
}

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Вы не можете использовать этот метод, потому что это метод расширения IEnumerable<T> (Average без параметров является группой методов расширения для IEnumerable<int>, IEnumerable<double> и т. Д.), А ваш FixedSizeQueue не реализует IEnumerable<T> интерфейс. Если вы реализуете это (и делегируете реализацию на _queue:

public class FixedSizeQueue<T> : IEnumerable<T> {
    private Queue<T> queue;

    public FixedSizeQueue(int capacity) {
        Capacity = capacity;
        queue = new Queue<T>(capacity);
    }

    public int Capacity { get; private set; }

    public int Count
    {
        get { return queue.Count; }
    }

    public void Clear() {
        queue.Clear();
    }

    public T Enqueue(T item) {
        queue.Enqueue(item);
        if (queue.Count > Capacity) {
            return queue.Dequeue();
        }
        else {
            //if you want this to do something else, such as return the `peek` value
            //modify as desired.
            return default(T);
        }
    }

    public T Peek() {
        return queue.Peek();
    }

    public IEnumerator<T> GetEnumerator() {
        return ((IEnumerable<T>) this.queue).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }
}

Тогда вы сможете использовать Average как обычно:

var queue = new FixedSizeQueue<float>(10);
var result = queue.Average();

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

var queue = new FixedSizeQueue<string>(10);
var result = queue.Average(x => x.Length);
0 голосов
/ 27 апреля 2018

Average работает только для следующих типов: decimal, int, long, float, double.

Сейчас ваша коллекция T, что невозможно усреднить. Вам нужно использовать селектор в вашей коллекции и записать его напрямую.

Пример, позвольте сказать, что у вас есть следующий класс

public class MyData
{
    public string Title {get;set;} = "";
    public double Value {get;set;} = 0d;
}

и скажем, что у вас есть очередь:

FixedSizeQueue<MyData> queue = new FixedSizeQueue<MyData>();
// add some data ...
queue.Enqueue(new MyData());

Теперь, чтобы получить среднее значение, вам нужно указать, что вы хотите усреднить, и здесь я хочу свойство Value, тогда я бы сделал это (очень явно)

double averageValue = queue.ToList().Average(data => data.Value);
...