假设我有一个整数队列(或任何 T 类),我可以更改队列中元素的值吗?更具体地说,如果我将队列定义如下:
Queue<int> q = new Queue<int>();
我们可以像处理数组一样更改其元素的值吗?(如果 q 是一个数组,我们可以做这样的事情:q[0]=1改变它的元素)。我只是想简化场景并以 int 为例,但我的意图是尝试查看队列中 T 类的第一项,进行一些计算并更新队列以供其他程序处理。我不想让它出队,因为队列中的序列将与原始序列不同。希望我想做的事情有意义。请指教。
如果队列中的项目是可变类型,那么您可以更改队列的第一个项目的值。如果不重新创建队列或执行大量入队/出队,则无法更改队列前面的项目。
作为第一种情况的示例,如果您有Queue<MyClass>一个定义为:
class MyClass
{
public string Value { get; set; }
}
Queue<MyClass> queue = new Queue<MyClass>();
queue.Enqueue(new MyClass() { Value = "1" });
queue.Peek().Value = 2;
string value = queue.Peek().Value; // is 2
您不能直接更改其中的项目Queue(尽管您可以使用Tudor 建议的解决方法)。但是如果你想有一个队列,你不必使用Queue. .Net 的另一种可能类型是LinkedList. 它允许您从两端添加和删除东西,可以在您的场景中使用:
LinkedList<int> list = new LinkedList<int>();
// enqueue an item
list.AddLast(1);
// dequeue an item
var item = list.First.Value;
list.RemoveFirst();
// put item back to the front of the queue
list.AddFirst(item);
您似乎想这样做以按顺序按几个模块处理每个项目。但我不确定这是做这种工作的正确方法。更好的方法可能是在每两个模块之间设置一个队列。一个模块总是从它的输入队列中取出一个项目,处理它,然后把它放到它的输出队列中。
这种方法的优点之一是更大的灵活性:一个模块可以在输出和输入上具有不同的类型,这对于“一个队列”方法是不可能的(除非你使用objects 的队列,或者类似的东西那)。
TPL Dataflow(.Net 4.5 中的新功能)使用这种方法通过并行化提高性能。它可以做到这一点,因为如果您没有单个中央队列,每个模块都可以独立于其他模块处理项目。
只要您存储的是类之类的引用类型,您对其所做的任何更改都会反映在队列中。下面代码的输出将是“2”:
public class MyClass
{
public int Value { get; set; }
}
static void Main(string[] args)
{
Queue<MyClass> q = new Queue<MyClass>();
q.Enqueue(new MyClass { Value = 1 });
var i = q.Peek();
i.Value++;
i = q.Peek();
Console.WriteLine(i.Value);
}
您可以使用一个简单的包装器:
class Wrapper<T>
{
public T Value { get; set; }
}
static void Main(string[] args)
{
Queue<Wrapper<int>> q = new Queue<Wrapper<int>>();
Wrapper<int> wr = new Wrapper<int> { Value = 1 };
q.Enqueue(wr);
Wrapper<int> wr1 = q.Peek();
wr1.Value = 2;
int value = q.Dequeue().Value;
Console.WriteLine(value);
}
public static class Extensions
{
public static Queue<T> SetFirstTo<T>(this Queue<T> q, T value)
{
T[] array = q.ToArray();
array[0] = value;
return new Queue<T>(array);
}
}
严格来说,这不会改变队列,因此需要重新分配。
[TestMethod]
public void Queue()
{
var queue = new Queue<int>(new[]{1,2,3,4});
queue = queue.SetFirstTo(9);
Assert.AreEqual(queue.Peek(),9);
}
简单回答是不。它不是 Queue 对象的 API 的一部分
http://msdn.microsoft.com/en-us/library/system.collections.queue.aspx
然而,当然一切皆有可能。您可以编写一个扩展方法来执行此操作,但它必须与对象的 API 一起使用,因此在保留顺序的同时将所有项目与更改一起出队/入队。
但是如果你想这样做,你就是把队列当作一个列表,那么为什么不使用一个列表呢?