【问题标题】:How to Invoke a function in a List in C#如何在 C# 中调用列表中的函数
【发布时间】:2018-02-13 01:55:31
【问题描述】:

我对 C# 还很陌生,并试图弄清楚如何从列表中调用函数。我认为 List 会完成我需要的工作。我可以将我的函数放入列表中,但我似乎无法实际调用它们。

首先我尝试了这个:

List<Action> randEvent = new List<Action>();

 void Test()
    {
        randEvent.Add(Test2);
        Invoke(randEvent(0), 0f);
    }

    void Test2()
    {
        print("This is a test of the random event system");
    }

那么这个

   List<Action> randEvent = new List<Action>();

   void Test()
    {
        randEvent.Add(Test2);
        randEvent(0);
    }

    void Test2()
    {
        print("This is a test of the random event system");
    }

但两者都不起作用。我究竟做错了什么?这甚至可能吗?我想这样做的原因基本上是我有 100 个函数,我希望我的程序在调用另一个函数时随机选择它们。

感谢任何解决方案,但请记住,我对 C# 和代码还是很陌生。提前致谢。

【问题讨论】:

  • randEvent 是如何定义的?请阅读How to Ask 并采取tour
  • 抱歉,在我的副本 Plutonix 中遗漏了那一行,感谢您指出。
  • 就问题描述而言,“但两者都不起作用”真的很差。编译器/运行时/调试器都提供了非常有用的信息(错误消息、堆栈跟踪等),关于您应该在问题中提出的“不工作”的性质。不这样做可能会被视为懒惰。
  • 我认为这没有必要甚至没有帮助,因为“不工作”纯粹是对语法的滥用。这些错误对阅读此问题的任何人都没有用。
  • @Rathlord 当然会。例如,在您提供的几百个字符的代码中,您将被告知错误在哪里。这对试图帮助你的人来说是有用的信息。更重要的是,通过花时间陈述所有事实,您可能会深入了解自己的问题。写一个 SO 问题是“talking to the duck”的一种形式。

标签: c# list unity3d


【解决方案1】:

在 C#/.NET 中,不同的方法签名具有代表它们的不同委托类型。 Action 表示不带参数且不返回值的函数,例如 void Foo()。如果要表示的函数采用float 参数并且不返回任何内容,则需要使用Action&lt;float&gt;。具有返回值的函数用Func 系列类型(Func&lt;T&gt;Func&lt;T1, T2&gt;...)表示。

List&lt;T&gt; 中只能放置一种委托,因此不能混合使用 Actions 和 Action&lt;float&gt;s。

要从 C# 中的列表中取出项目,请使用 [n]。喜欢

List<Action> actions = new List<Action>();
actions.Add(Foo);
Action a = actions[0];

要在 C# 中调用委托实例,请在其上调用 Invoke 方法,或者只使用 (),这是调用 Invoke 的简写。对于ActionInvoke 采用 0 个参数,对于 Action&lt;T&gt; 它采用单个 T 参数,等等。

所以对于你的整个例子:

List<Action> actions = new List<Action>();

void Test()
{
    actions.Add(PrintStuff);
    actions[0]();
    //or
    actions[0].Invoke();
    //or
    foreach (var a in actions) a();
}

void PrintStuff()
{
    print("This is a test of the random event system");
}

【讨论】:

  • 这正是我所需要的,我所要做的就是将这一行改为:randEvent[0]();非常感谢!
【解决方案2】:

你可以声明一个Action 的列表,每个对象都会指向一个特定的方法。示例;

IList<Action> actionList = new List<Action>();
actionList.Add(() => Test2());

然后你可以循环遍历列表和Invoke每个方法。

foreach(var method in actionList)
{
    method.Invoke();
}   

【讨论】:

  • 你不需要做Add( () =&gt; Test2() ),你可以做Add( Test2 )。 lambda 只是增加了一个无用的间接层和闭包的性能开销。
  • 我希望随机调用它们,这就是我这样做的原因。所以我需要一种方法来一次调用它们,基于我输入的随机数。不希望一次完成所有事情,也不按顺序完成。不过感谢您的回复。
  • @Rathlord 一旦生成了索引,就可以在列表中传递该值来获取方法。 actionList[3].Invoke(); 假设 3 是一个随机数
  • 感谢所有帮助 - 找到了一个更简单的解决方案(至少让我的头绕起来),但我真的很感激时间。
【解决方案3】:

我假设randEventList&lt;EventHandler&gt;List&lt;Action&lt;Int32&gt;&gt;

使用Delegate.Invoke( args )(因为EventHandlerAction&lt;T&gt; 都是Delegate 子类型)。

randEvent[0].Invoke( 123 );

在 C# 中,您也可以直接在 Delegate 上使用 ()

randEvent[0]( 123 );

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多