在队列中查找特定操作的索引

时间:2017-12-11 16:51:53

标签: c# indexing queue

所以我正在创建一个动作队列,它可以在任何时间调用,我需要的是获得每个会话队列位置。 我尝试过做一个行动队列,传递会话名称,而不是查找索引,但总是返回-1。

public static Queue<Action<string>> myQ = new Queue<Action<string>>();
static void Main(string[] args)
{
    myQ.Enqueue((string i) =>
    {
        i = "First";
    });
    myQ.Enqueue((string i) =>
    {
        i = "Second";
    });
    myQ.Enqueue((string i) =>
    {
        i = "Third";
    });
    int index = myQ.ToList().IndexOf((string i) =>
    {
        i = "First";
    });
    Console.WriteLine(index);
    Console.ReadLine();
}

1 个答案:

答案 0 :(得分:1)

List<T>.IndexOf方法搜索列表中的指定对象。对于引用类型(并且Action<string>是引用类型),项目通过引用相等性进行比较,即对象变量实际上应该引用相同的对象。

在您的情况下,每次指定

时都会创建一个新的Action<string>对象
(string i) =>
{
    i = "First";
}

这就是IndexOf()调用返回-1的原因。

最简单的修复方法是将同一个对象传递给IndexOf()调用:

var firstAction = (string i) =>
        {
            i = "First";
        };
myQ.Enqueue(firstAction);

// ...

int index = myQ.ToList().IndexOf(firstAction);

更灵活的方法是定义一个简单的类,该类具有会话名称作为您可以搜索的属性:

public class QueueItem
{
    public string SessionName { get; }

    public Action<string> Action => i => i = SessionName;

    public QueueItem(string sessionName)
    {
        SessionName = sessionName;
    }
}

Queue<QueueItem> myQ = new Queue<QueueItem>();
myQ.Enqueue(new QueueItem("First"));
myQ.Enqueue(new QueueItem("Second"));
myQ.Enqueue(new QueueItem("Thrid"));
int index = myQ.ToList().FindIndex(x => x.SessionName == "First");

代码中的另一个问题是如何使用Action分配字符串变量。请考虑以下代码:

string str = "One";
Action<string> action = x => x = "Two";
action(str);

执行此代码后,str的值为"One",而不是"Two"。调用操作时,str按值传递,因此对操作(或任何其他方法)内的参数的任何赋值都不会影响其初始值。有关详细信息,请查看此question

您可以通过Func<string>代替Action<string>并在分配中使用返回值来解决此问题:

public class QueueItem
{
    public string SessionName { get; }

    public Func<string> Func => () => SessionName;

    public QueueItem(string sessionName)
    {
        SessionName = sessionName;
    }
}

Queue<QueueItem> myQ = new Queue<QueueItem>();
myQ.Enqueue(new QueueItem("First"));
myQ.Enqueue(new QueueItem("Second"));
myQ.Enqueue(new QueueItem("Thrid"));
var queueList = myQ.ToList();
int index = queueList.FindIndex(x => x.SessionName == "First");
var result = queueList[index].Func();