我有两个简单的课程。一个被称为UseCounter<T>
并且是其他对象的简单容器,同时保存有关其使用的一些信息(已经使用了多少次以及它是否可以再次重复使用)。
然后有Dispenser<T>
,其中包含UseConter<T>
的集合,用于从集合中获取正确的元素,然后更新其信息。
我遇到的麻烦在于Dispenser的Get()
方法。它应该返回Count
和TotalCount
的最低组合的对象,然后调用Increase()
方法以增加计数。
但是,当我运行此代码时,Dispenser<T>
始终返回相同的元素。它就像Linq的元素不是对象的引用,而是它的副本,因此Increase()
方法只增加本地对象的属性,但不会增加在集合中。
我在这里感到茫然,因为我从未遇到过这样的行为。
代码如下:
UseCounter:
public class UseCounter<T>
{
public T Element { get; private set; }
public int TotalCount { get; private set; }
public int Count { get; private set; }
public bool Useful { get; set; }
public UseCounter(T element)
{
this.Element = element;
this.Count = 0;
this.TotalCount = 0;
this.Useful = true;
}
public void IncreaseCounter()
{
this.Count++;
this.TotalCount++;
}
public void DecreaseCounter()
{
if(this.Count == 0)
{
throw new ArgumentOutOfRangeException("Count cannot be lower than 0!");
}
this.Count--;
}
}
的分配器:
private readonly object _elementLocker = new object();
private IEnumerable<UseCounter<T>> _elements;
public IEnumerable<T> Elements
{
get { return _elements.Select(e => e.Element); }
}
public int FinishedCount
{
get
{
lock (_elementLocker)
{
return _elements.Where(e => e.Useful == false).Count();
}
}
}
public int CurrentlyWorkingCount
{
get
{
lock (_elementLocker)
{
return _elements.Where(e => e.Count > 0).Count();
}
}
}
public Dispenser(IEnumerable<T> elements)
{
this._elements = elements
.Distinct()
.Select(e => new UseCounter<T>(e));
}
public T Get()
{
lock(_elementLocker)
{
var lCount = _elements
.Where(e => e.Useful == true)
.Select(e => e.Count).Min();
var lTCount = _elements
.Where(e => e.Useful == true)
.Where(e => e.Count == lCount)
.Select(e => e.TotalCount).Min();
var el = _elements
.Where(e => e.Useful == true)
.First(e => e.Count == lCount && e.TotalCount == lTCount);
el.IncreaseCounter();
return el.Element;
}
}
public void Report(T element, bool successful)
{
lock(_elementLocker)
{
var el = _elements
.First(e => e.Element == element);
el.DecreaseCounter();
if(el.Useful == true && successful == true)
{
el.Useful = false;
}
}
}
答案 0 :(得分:3)
这是问题所在:
this._elements = elements
.Distinct()
.Select(e => new UseCounter<T>(e));
这很懒惰。每次迭代_elements
时,它将返回到原始源数据,找到一个不同的集合,然后将该集合投影到UseCounter
个实例的新序列上。您对这些实例所做的任何更改都与下次迭代_elements
时发生的情况无关。
如果您对构造中的“冻结”输入元素集很满意,您可以实现查询,使其只执行一次:
this._elements = elements
.Distinct()
.Select(e => new UseCounter<T>(e))
.ToList();
现在每次迭代elements
时,你都会迭代相同的引用序列。