这是How do I pass a function pointer delegate for a different class in c#
的后续问题我有一个班级
public class ClassA
{
public void Foo()
{
Console.WriteLine("Foo()");
}
public void Foo(int x, int y)
{
Console.WriteLine("Foo(" + x.ToString() + ", " + y.ToString() + ")" );
}
public void Foo(int x, int y, int z)
{
Console.WriteLine("Foo(" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ")" );
}
}
在另一种方法中,我想像这样调用classA的类函数:
ClassA obj = new ClassA();
TakesFun(obj.Foo);
TakesFun(obj.Foo, 1, 2);
TakesFun(obj.Foo, 1, 2, 3);
TakesFun的语法应该是什么?我想把它变成泛型来接受很多/ any / none参数并根据参数的数量调用适当的函数?
显然下面的函数语法是错误的,但我正在寻找一个类似的函数。
public static void TakesFun<TParam>(Action<TParam[]> action, params TParam[] paramList)
{
Console.WriteLine("TakesFun");
action(paramList);
}
EDIT1:ClassA Foo函数只是一个例子。我想调用更复杂的函数,可以采取任何形式的论证。 喜欢例如:
public void CleanList(List<int> l)
{
l.Clear();
}
答案 0 :(得分:6)
在另一种方法中,我想像这样调用classA的类函数: TakesFun(obj.Foo);
接下来请注意,TakesFun
是一个采用Action
的方法,而不是一组重载方法。
你无法得到你想要的东西,你必须学会忍受失望。 C#不支持您想要的功能。
您正在将obj.Foo
从方法组表单转换为委托表单,这需要C#执行重载解析通过将TakesFun
的形式参数列表中的委托与名为Foo
的方法集合进行比较,然后选择最佳方法。
因为没有最好的&#34;在编译时,这将失败。
找到解决问题的另一种方法。 你的问题听起来非常像我们称之为&#34; XY问题&#34;。也就是说,你有一些真正的问题,你对如何解决它有一个疯狂的想法永远不会有效,现在你问一个关于你疯狂想法的问题。问一个关于真正问题的问题。几乎可以肯定,有一种比这更好的解决方法。
现在,如果我们放松一些问题的限制,那么我们就可以做到。特别是,如果我们放宽只有一个TakesFun
并且它是可变参数的约束,那么我们就可以做到。我注意到TakesFun
实际上是函数应用程序操作:
static void Apply(Action action) => action();
static void Apply<A>(Action<A> action, A a) => action(a);
static void Apply<A, B>(Action<A, B> action, A a, B b) => action(a, b);
static void Apply<A, B, C>(Action<A, B, C> action, A a, B b, C c) => action(a, b, c);
... and so on, as many as you need
现在重载决议的魔力解决了你的问题:
Apply(obj.Foo, 1, 2, 3); // Works fine
重载决议推断Apply
表示Apply<int, int, int>
,Action
为Action<int, int, int>
,而Foo
表示采用三个整数。
C#类型推断非常好,但你必须在我们设计成语言的范围内使用它。
更新:根据您的评论,听起来您正在尝试重新创建任务并行库。我会调查TPL,看看它是否已满足您的需求。
在C#中,我们代表将来作为Task
执行的工作单元的概念;有一个巨大的库和内置语言支持,用于组合任务中的工作流程,将其延续安排到各种线程,等等。 使用此作品而非尝试自己发明。
例如,如果您想要创建代表未来工作的未启动任务,您可以这样做:
static Task TaskFactory(Action action) => new Task(action);
static Task TaskFactory<A>(Action<A> action, A a) => new Task(()=>action(a));
static Task TaskFactory<A, B>(Action<A, B> action, A a, B b) => new Task(()=>action(a, b));
等等。现在你可以做到:
Task t = TaskFactory(obj.Foo, 1, 2);
并获取t
启动时将执行操作。然后,您可以说出任务完成后您想要发生的事情:
t.ContinueWith(task => Console.WriteLine("Task complete!"));
然后启动它:
t.Start();
有一些机制可用于创建已在工作线程上启动和运行的任务。有一些机制用于调度任务或其完成以在特定线程上运行。等等;这是一个巨大的主题。如果您对此有疑问,请提出其他问题。