向扩展添加方法
Adding methods to extensions
我找到了一些代码来制作固定大小 here 的 Queue
。现在我正在尝试为此添加一个 Average
方法,但我收到消息:
'Queue' does not contain a definition for 'Average' and the best extension method overload 'Queryable.Average(IQueryable)' requires a receiver of type 'IQueryable'
对于正常的 Queue
我可以使用 Average
方法。为什么我不能在这里访问它?
同样先转换为数组或列表再取平均值也不行:queue.ToArray().Average()
.
最后,为什么最好将此扩展包装在新的 class 中,而不是通过 public class FixedSizeQueue<T> : Queue<T>
从 Queue
继承?
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();
//}
}
Average
仅适用于以下类型:decimal
、int
、long
、float
、double
。
现在您的 collection 是 T
,这是无法平均的。
你需要在你的collection上使用一个选择器,直接写下来。
例如,假设您有以下 class
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);
不能使用此方法,因为它是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);
我找到了一些代码来制作固定大小 here 的 Queue
。现在我正在尝试为此添加一个 Average
方法,但我收到消息:
'Queue' does not contain a definition for 'Average' and the best extension method overload 'Queryable.Average(IQueryable)' requires a receiver of type 'IQueryable'
对于正常的 Queue
我可以使用 Average
方法。为什么我不能在这里访问它?
同样先转换为数组或列表再取平均值也不行:queue.ToArray().Average()
.
最后,为什么最好将此扩展包装在新的 class 中,而不是通过 public class FixedSizeQueue<T> : Queue<T>
从 Queue
继承?
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();
//}
}
Average
仅适用于以下类型:decimal
、int
、long
、float
、double
。
现在您的 collection 是 T
,这是无法平均的。
你需要在你的collection上使用一个选择器,直接写下来。
例如,假设您有以下 class
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);
不能使用此方法,因为它是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);