【问题标题】:way to define functions in parameters in order to pass one, out of two, functions as an argument在参数中定义函数以便将两个函数中的一个作为参数传递的方法
【发布时间】:2016-08-26 09:01:30
【问题描述】:

我的程序有一个简单的函数 newline(),它将为 int 变量 x 提供一个 int 值。

public void autowordwrap(string wrapthisword)
{
//some code that does things irrelevant to this problem, with the string

x=newline();

//assume x is already declared properly
//do something with value from x
}

当我引入一个新函数 sameline()

时问题就开始了

我希望能够一次方便地完成其中任何一项:

public void autowordwrap(string wrapthisword)
{
x=newline();
}

或者,

public void autowordwrap(string wrapthisword)
{
x=sameline();
}

所以,我想到了尝试这个:

public void autowordwrap(string wrapthisword, Func<void,int> linefunc)
{
x=linefunc;
}

我稍后可以将要求称为:

autowordwrap(mystring,newline());

或者,

autowordwrap(mystring,sameline());

但这对我来说不太有效!

它说关键字'void'不能在这种情况下使用

问题是:

我想要做的应该足够简单,但我不太了解它是如何工作的。我知道 Action 适用于没有返回类型的函数,而 Func 适用于有返回类型的函数。[Reference-1]

到目前为止我收集到的是:

  1. MSDN tells me: 要引用没有参数并返回 void 的方法(或者在 Visual Basic 中,声明为 Sub 而不是函数),请改用 Action 委托。

    • 由于我的 newline() 函数被定义为 int 数据类型,并且它在运行后返回一个整数,所以我认为 Action 不适合我的需要。
  2. This answer 有我需要的东西,但对于我的生活,我无法让它为我的特定目的工作。

问题分解

  • 我有两个函数 newline() 和 sameline()
  • 我希望将其中的任何 一个作为函数 autowordwrap() 的参数传递

这意味着,在我的主程序中,我将在必要时使用 autowordwrap(somestring, newline());autowordwrap(somestring, sameline());

  • newline() 和 sameline() 都是 int 数据类型函数,它们在被调用时返回整数值。为了解决这个问题,让我们将它存储在 int x
  • 尝试解决这个问题时,我假设在调用 example: newline( void)int 部分用于将函数 newline() 或委托 Func 表示的任何函数定义为返回 int 值的函数。
  • 我已经意识到,我所学到的似乎在某些地方存在根本性的缺陷。请赐教。参考链接也会很有帮助。
  • 以任何方式解决此问题都是可以接受的。您不需要以我可能无意中严格概述的方式执行此操作。只要满足 C# 的预期目的,请随意探索创造性的解决方案

是的,我承认这可能与 this question 重复,但我无法理解那里发布的有用答案。假设许多未来的读者都会遇到这种情况,我提出这个问题并将其链接到that question,以便将来可能会遇到同样问题的人有所帮助。


尾注:

这个问题已经解决了!标记的答案为执行此操作奠定了基础,there is also some great explanation in the answers. 如果您在解决此类类似问题时遇到一些错误,您也许可以通过查看我自己错误的屏幕截图来解决这些问题。 They're here in the revision section no.4

【问题讨论】:

  • 我已经为你回答了这个问题——比如 newline() 之后删除括号——这会将换行函数传递给你的函数。你正在做的是传入一个整数,它期望一个方法,当调用时,返回一个整数。
  • 您的编辑非常反对您应该如何提问。它非常长,非常冗长,它有大量不需要的图片(如果这些图片完全相关,请使用代码块),更糟糕的是你的原始问题没有这些问题。阅读How to Ask 并回滚您的帖子。
  • @Amit :正如我在问题中提到的,屏幕截图是对 cme​​ts 中提出的请求的响应。有人问他们,因为他们没有清楚地了解我的问题。所以我只是按照他们的要求做了。有没有张不需要的图片。错误列表对于查明问题是必要的。我最初的问题是基于我假设的解决方案。它是一个大纲,因此不会遇到我应用一些建议时遇到的相同错误。如果有人想理解这个问题,我认为这是必要的,因此我为我的行为辩护。祝你有美好的一天!

标签: c# delegates


【解决方案1】:

由于您的函数不需要委托,它需要int,您最好完全避免委托,只需传递int 值,然后执行以下操作:

public void autowordwrap(string wrapthisword, int separator)
{
  //some code that does things irrelevant to this problem, with the string

  // if you need it in "x"
  x=separator;

  //do something with value from x
}

autowordwrap(mystring,newline());

// or

autowordwrap(mystring,sameline());

创建干净的高质量代码的总体思路是让函数接受执行其特定任务所需的值,而不是一些“更大”的复杂输入。

【讨论】:

  • 嗯,不出所料,它可以顺利运行!我想知道这样一个优雅的解决方案是如何让我忘记的。做得好!它解决了这个问题并为此+1。但我也想了解委托,因此我将保留标记和答案以获得最佳答案,以解决任何可以实际传递的函数。道具和 +1 的简单和创造性的答案:)
【解决方案2】:

你就快到了。有几个问题。

首先,从您的代码中,您似乎将函数的结果传入;

 autowordwrap("foo", newline());

在这段代码中,C# 将调用换行函数,得到一个结果。然后它将该函数的结果——你的 int——作为第二个参数传递给 autowordwrap。

您想要做的是传入未调用的函数本身;

autowordwrap("foo", newline);

只要newline 函数的签名与自动换行所需的签名兼容,您就可以在自动换行中调用该函数。

第二部分不是Func&lt;&gt;Action&lt;&gt; 之间的区别,而是关于泛型参数。

你想要的签名是一个不带参数并返回一个int的函数。所以尝试是合理的

Func<void, int>

但实际上,Func&lt;&gt; 可以采用任意数量的泛型类型。除了最后一个都是参数;最后是返回值。所以

Func<string, string, int>

对应于类似

的方法
public int MyFunction(string s1, string s2) { return 0; }

你正在尝试的是一个没有参数的函数,相当于

public int MyFunction() { reutrn 0; }

所以你要找的签名是

Func<int>

也就是一个没有参数的函数,返回int。为了清楚起见,

Action<int>

接受一个整数参数并且不返回任何内容,相当于

public void MyAction(int myParam) { }

--

哦,澄清一下;

 Func<void, int>

不起作用,因为它相当于用 C# 编写这个

 public int MyFunction(void x) {}

这就像说'一个带有一个参数的函数,它是一个'void'类型的变量'。这没有意义,因此编译器错误。

【讨论】:

  • 感谢您的全面解释。 +1。我正在根据它对我的工作方式编写一个演练评论。通过在作为参数传递时从 newline() 中删除括号来解决。在使用时给 linefunc 添加括号也很重要。 示例: 函数被称为 autowordwrap(mystring,newline) 并且函数被声明并且委托被用作 public void autowordwrap(string mystring , 函数 linefunc){x=linefunc();}
【解决方案3】:

Func&lt;T&gt;必须返回一些东西,它不能是无效的,你必须使用Action&lt;T&gt;,如果你不想返回任何东西。

如果您不想将任何输入参数传递给Func&lt;T&gt;,那么您只需要一个返回类型的参数,例如:

Func<int> linefunc

您不能将Func&lt;T,TResult&gt; 的输入类型参数定义为void,而只是删除它的输入类型参数,

您的方法定义如下所示:

public void autowordwrap(string wrapthisword, Func<int> linefunc)
{
  x=linefunc();
}

然后这样称呼它:

autowordwrap(mystring, newline);
autowordwrap(mystring, sameline);

【讨论】:

  • 我希望它返回一些东西。我希望它返回 newline() 或 sameline() 将返回的 int 值。但是,我不一定需要在 autowordwrap() 之外使用它。我这样做是假设 func 定义了它正在运行的函数。我的函数 newline() 和 sameline() 都不需要参数(因此为 void),但返回一个 int 值。我该怎么做呢?我很困惑
  • 查看我更新的帖子,您只需传递一个类型参数,即 TResult
  • 跟进您最近的编辑,现在我收到一条错误消息,提示“无法从 'int' 转换为 'System.Func'。您能告诉我这里的转换类型吗?
  • 我是否也需要更改声明 newline() 的方式?因为我仍然遇到错误。我目前已将其声明为:public void newline(){//stuff} 这需要更改吗?错误是:“无法从 'System.Func' 转换为 'int'” | “无法将 lambda 表达式转换为委托类型 'System.Func',因为块中的某些返回类型不能隐式转换为委托返回类型。” | “无法将方法组 'newline' 转换为非委托类型 'int'。您是否打算调用该方法?” | 这让我相信改变是必要的?
  • 您的换行符和同一行需要返回一个 int 以匹配委托签名,因为委托返回类型也是 int
猜你喜欢
  • 2017-08-07
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
  • 2022-11-12
  • 1970-01-01
  • 2021-12-11
  • 2015-12-04
  • 2014-02-14
相关资源
最近更新 更多