使用参数调用函数列表的简单方法?

时间:2014-07-30 18:47:06

标签: c# list delegates action

我正在寻找一种简单的方法来创建一个带有可以调用的参数的函数列表。我几乎做到了但是将方法设置为参数之一存在一些问题。 这是我的代码:

public class PlayerInfo
{
    public static PlayerInfo Instance; // singleton

    public int Energy;
    public int MaxEnergy;
    public List<KeyValuePair<DateTime, cronTab>> cron;

    //some update event for instance every frame of game
    void Update() {
        var keys = cron;
        for (int k=0;k<keys.Count;k++) {
            if (keys[k].Key.CompareTo(System.DateTime.Now) < 0 )
            {
                keys[k].Value.function.Invoke(keys[k].Value.parameter);
                cron.RemoveAt(k);
            }
        }
    }

    public static void addEnergy(DateTime date)
    {
        if (PlayerInfo.Instance.Energy < PlayerInfo.Instance.MaxEnergy)
            PlayerInfo.Instance.Energy++;
        date = date.AddSeconds (10);
        PlayerInfo.Instance.cron.Add (new KeyValuePair<DateTime, cronTab>(date, new cronTab(){type = CronType.energy, function = (Action<System.Object>)PlayerInfo.addEnergy, parameter = date}));
    }
}

public class cronTab
{
    public CronType type;
    public System.Object parameter;
    public Action<System.Object> function;
}

public enum CronType
{
    energy,
    mail
}

问题在于A method or delegate 'PlayerInfo.addEnergy(System.DateTime)' parameters do not match delegate 'System.Action<object>(object)' parameters和我Cannot convert method group 'addEnergy' to non-delegate type 'System.Action<object>'.你有什么想法我怎么可能解决它?

3 个答案:

答案 0 :(得分:1)

使用此:

function = ((obj) => PlayerInfo.addEnergy((DateTime)obj))

之前无法使用,因为您的delegate声明它需要object,但您尝试将其设置为(addEnergy)的功能需要DateTime

请注意,System.Object相当于object

此外,如果每个cronTab.function都需要DateTime,那么您应该将其设为Action<DateTime>。如果您进行此更改,则可以使用原始代码:

function = PlayerInfo.addEnergy

(请注意,此处不需要转换为Action<DateTime>,因为PlayerInfo.addEnergy已经是正确的类型。)

答案 1 :(得分:1)

当您在此处仅使用委托Action时,一切都变得更加容易。没有一个类跟踪要发送的参数,不要尝试处理不同数量或类型的参数。试图这样做是一个巨大的混乱,必要时,删除所有静态类型安全。

而是关闭创建委托时所需的任何参数,以将方法从它变为Action

public class CronTab
{
    public CronType type;
    public Action action;
}

public static void addEnergy(DateTime date)
{
    if (PlayerInfo.Instance.Energy < PlayerInfo.Instance.MaxEnergy)
        PlayerInfo.Instance.Energy++;
    date = date.AddSeconds(10);
    PlayerInfo.Instance.cron.Add(
        new KeyValuePair<DateTime, CronTab>(
            date,
            new CronTab()
            {
                type = CronType.energy,
                action = () => PlayerInfo.addEnergy(date),
            }));
}

答案 2 :(得分:0)

编译器对你大吼大叫,因为你的方法与委托的签名不兼容。你需要改变

public Action<System.Object> function;

public Action<DateTime> function;

或需要更改

public static void addEnergy(DateTime date)

public static void addEnergy(object date)

然后删除以下行中的显式委托转换

PlayerInfo.Instance.cron.Add (new KeyValuePair<DateTime, cronTab>(date, new cronTab(){type = CronType.energy, function = PlayerInfo.addEnergy, parameter = date}));