向扩展添加方法

时间:2018-04-27 12:42:38

标签: c# queue extension-methods

我找到了一些代码来制作固定大小hereQueue。现在我尝试为此添加Average方法,但我收到了消息:

  

'队列'不包含'平均值'的定义和最好的扩展方法重载' Queryable.Average(IQueryable)'需要一个类型为“IQueryable'

的接收器

对于正常Queue,我可以使用Average方法。为什么我不能在这里访问它?

首先转换为数组或列表,然后取平均值不起作用:queue.ToArray().Average()

最后,为什么最好将此扩展包装在新类中,而不是通过执行Queuepublic 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 :(得分:1)

您无法使用此方法,因为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);

答案 1 :(得分:0)

Average仅适用于以下类型:decimalintlongfloatdouble

目前您的收藏集是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);