将委托和参数一起传递给函数

本文关键字:函数 一起 参数 | 更新日期: 2023-09-27 18:24:19

我想将任务列表排入队列,然后对某个事件执行。代码:

internal class MyClass
{
    private Queue<Task> m_taskQueue;
    protected MyClass()
    {
        m_taskQueue = new Queue<Task>();
    }
    public delegate bool Task(object[] args);
    public void EnqueueTask(Task task)
    {
        m_taskQueue.Enqueue(task);
    }
    public virtual bool Save()
    {
        // save by processing work queue
        while (m_taskQueue.Count > 0)
        {
            var task = m_taskQueue.Dequeue(); 
            var workItemResult = task.Invoke();
            if (!workItemResult) 
            {
                // give up on a failure
                m_taskQueue.Clear();
                return false;
            }                
        }
        return true;
    }
}

每个委托任务都可能有自己的参数列表:task(object[]args)。我的问题是如何将参数传递给任务队列的每个任务?

将委托和参数一起传递给函数

好吧,现在我们有了更多的信息,听起来你的EnqueueTask方法实际上应该是这样的:

public void EnqueueTask(Task task, object[] values)

对吧?

对于初学者,我会避免使用名称Task,它已经是.NET 4核心的一部分,并且将在.NET 5中变得非常突出。正如约书亚所说,你基本上有一个Func<object[], bool>

接下来,可以保留两个列表-一个用于委托,一个用于值,但只保留这样的Queue<Func<bool>>更容易:

private readonly Queue<Func<bool>> taskQueue = new Queue<Func<bool>>();

public void EnqueueTask(Task task, object[] values)
{
    taskQueue.Enqueue(() => task(values));
}

然后,您的代码的其余部分将"按原样"工作。那里的lambda表达式将捕获valuestask,因此当您调用Func<bool>时,它将向原始委托提供这些值。

如果正确理解您的问题,您只需像普通电话一样传递信息。你考虑过使用Func吗?您可以将参数传递给Task.Invoke,即Task.Invoke([arguments here as a *single* object array])

object[] arguments = null; // assign arguments to something
var workItemResult = task.Invoke(arguments);

下面是一个使用Func类型的示例。

internal class MyClass
    {
        private Queue<Func<object[], bool>> m_taskQueue;
        protected MyClass()
        {
            m_taskQueue = new Queue<Func<object[], bool>>();
        }

        public void EnqueueTask(Func<object[], bool> task)
        {
            m_taskQueue.Enqueue(task);
        }
        public virtual bool Save()
        {
            object[] arguments = null; // assign arguments to something
            // save by processing work queue
            while (m_taskQueue.Count > 0)
            {
                var task = m_taskQueue.Dequeue();
                var workItemResult = task(arguments);
                if (!workItemResult)
                {
                    // give up on a failure
                    m_taskQueue.Clear();
                    return false;
                }
            }
            return true;
        }
    }