gpt4 book ai didi

c# - 如何将可变参数传递给根据参数数量调用特定函数的函数?

转载 作者:太空宇宙 更新时间:2023-11-03 18:53:35 27 4
gpt4 key购买 nike

这是对 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 的语法应该是什么?我想让它变得通用以接受许多/任何/无参数并根据参数的数量调用适当的函数?

显然下面的函数语法是错误的,但我正在寻找一个类似的函数。

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();
}

最佳答案

In another method, I would like to call the class functions of classA like this: TakesFun(obj.Foo);

您继续注意到 TakesFun 是采用 Action 的单个方法,而不是重载方法的集合。

你不可能总是得到你想要的,你必须学会​​忍受失望。 C# 不支持您想要的功能。

您正在将 obj.Foo方法组形式转换为委托(delegate)形式,这需要 C# 通过比较委托(delegate)来执行重载解析TakesFun 的形参列表中加入名为 Foo 的方法集合,然后选择最好的一个。

由于在编译时没有“最好的”,这将失败。

寻找另一种方法来解决您的问题。 您的问题听起来很像我们所说的“XY 问题”。也就是说,您遇到了一些真正的问题,您对如何解决它有一个永远行不通的疯狂想法,现在您'问一个关于你的疯狂想法的问题。问一个关于真正问题的问题。几乎可以肯定,有比这更好的解决方法。

现在,如果我们放宽您的问题的一些限制,那么我们就可以做到。特别是,如果我们放宽只有一个 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>ActionAction<int, int, int> 并且 Foo 意味着取三个整数。

C# 类型推断非常好,但您必须在我们为语言设计的范围内使用它。


更新:根据您的评论,听起来您正在尝试重新发明任务并行库。我会调查 TPL,看看它是否已经满足您的需求。

在 C# 中,我们将将来要执行的工作单元的概念表示为 Task ;有一个巨大的库和内置语言支持,用于从任务中组合工作流,将它们的延续安排到各种线程,等等。 使用这项工作而不是尝试自己发明

例如,如果您想创建代表 future 工作的未开始任务,您可以这样做:

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();

有一些机制可以创建已经启动并在工作线程上运行的任务。有调度任务或它们的完成在特定线程上运行的机制。等等;这是一个庞大的话题。如果您对此有疑问,请提出另一个问题。

关于c# - 如何将可变参数传递给根据参数数量调用特定函数的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50915880/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com