在自定义队列包装器中实现Average方法

时间:2018-05-01 19:49:25

标签: c# .net unity3d queue average

我有一个自定义'可锁定'队列类,它包装了队列。但它缺少一个平均方法。

这是我尝试添加到下面的源链接中列出的类的平均方法

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

但在'队列'

上收到以下错误
  

队列不包含“平均”和最佳定义   方法扩展重载'Enumerable.Average(IEnumerable)'   需要一个'IEnumerable'类型的接收器

原始来源https://gist.github.com/jaredjenkins/5421892

2 个答案:

答案 0 :(得分:0)

由于您明确地在类中定义了一些可以聚合以获得平均值的字段或属性,因此您可以选择在构造函数中定义lambda选择器函数,该函数将用于在执行时进行求值。唯一需要注意的是,字段/属性必须是公开可见的,因为它是在外部定义的。这个简单的类应该完成你想要做的事情。我注意到linq.Average()的默认返回类型是double而不是float。所以我改变了这一点,但除此之外它应该足够了。

CASE WHEN (TYPE = 'E') THEN (DENSE_RANK() OVER (PARTITION BY ID,TYPE ORDER BY NAME) + DENSE_RANK() OVER (PARTITION BY ID, TYPE ORDER BY NAME DESC) - 1) ELSE 0 END AS NC_E,

CASE WHEN (TYPE = 'M') THEN (DENSE_RANK() OVER (PARTITION BY ID,TYPE ORDER BY NAME) + DENSE_RANK() OVER (PARTITION BY ID, TYPE ORDER BY NAME DESC) - 1) ELSE 0 END AS NC_M,

CASE WHEN (TYPE = 'D') THEN (DENSE_RANK() OVER (PARTITION BY ID,TYPE ORDER BY NAME) + DENSE_RANK() OVER (PARTITION BY ID, TYPE ORDER BY NAME DESC) - 1) ELSE 0 END AS NC_D,

CASE WHEN (TYPE = 'C') THEN (DENSE_RANK() OVER (PARTITION BY ID,TYPE ORDER BY NAME) + DENSE_RANK() OVER (PARTITION BY ID, TYPE ORDER BY NAME DESC) - 1) ELSE 0 END AS NC_C

样本类型

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;
}

这样,您可以保证在编译时类型的选择器可用,并且您不必对队列类的泛型类型设置约束。

答案 1 :(得分:0)

嗯,从源代码看起来你可以用这种方式实现这个方法:

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

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

正如@Evk在注释中提到的,为了使用LINQ Average(),类型必须是数字。没有办法将泛型类型限制为C#中的数字,因此必须以某种方式将类型转换为数字。显然,对于可能位于自定义队列包装器中的所有类型,此方法或任何其他方法都不安全。