在参数中定义函数的方法,以便将两个函数作为参数传递

时间:2016-05-01 15:09:11

标签: c# delegates

我的程序有一个简单的函数 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());

但这对我来说不太合适!

  

它表示关键字&#39; void&#39;不能在这种情况下使用

问题是:

我想做的事情应该足够简单,但我不太了解它是如何运作的。我了解操作&lt;&gt; 适用于没有返回类型的函数,而 Func&lt;&gt; 适用于具有返回类型的函数。[Reference-1]

到目前为止我收集的是:

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

    • 由于我的newline()函数被定义为int-datatype,并且在运行后返回一个整数,我认为Action&lt;&gt;不适合我的需要。
  2. This answer拥有我所需要的东西,但对于我的生活,我无法使其符合我的特定目的。

  3. 问题细分

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

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

    • newline()和sameline()都是int-datatype函数,在调用时返回整数值。为了解决这个问题,我们将其存储在 int x
    • 尝试解决此问题时,我假设在调用示例时,使用Func用于将任何内容传递给函数作为参数: newline(void) int 部分用于定义函数newline()或由委托Func&lt;&gt;表示的任何函数。作为返回 int 值的那个。
    • 我已经意识到,我似乎学到的东西必须在某种程度上存在根本性的缺陷。请赐教。参考链接也非常有用。
    • 以任何方式解决此问题都是可以接受的。您不需要以我无意中严格概述的方式执行此操作。只要符合C#
    • 的预期目的,请随时探索创意解决方案
      

    是的,我承认这可能是 this question 的副本,但我无法理解那里发布的有用答案。假设,对于许多未来的读者来说,情况就是如此,我提出这个问题并将其与that question联系起来,以便它可能对将来会面临同样问题的人有所帮助。

    尾注:

      

    这个问题已经解决了!明确的答案为这样做奠定了基础和there is also some great explanation in the answers.如果你在解决这种性质的类似问题时遇到一些错误,你可能能够修复我自己看错的截图。 They're here in the revision section no.4

3 个答案:

答案 0 :(得分:3)

Func<T>必须返回一些内容,它不能无效,如果您不想返回任何内容,则必须使用Action<T>

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

Func<int> linefunc

您无法将Func<T,TResult>的输入类型参数定义为void,而只是删除它的输入类型参数,

您的方法定义如下:

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

并称之为:

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

答案 1 :(得分:3)

你几乎就在那里。有几个问题。

首先,从您的代码中,您似乎正在传递函数的结果;

 autowordwrap("foo", newline());

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

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

autowordwrap("foo", newline);

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

第二部分并不是Func<>Action<>之间的差异,而是关于通用参数。

您想要的签名是一个不带参数并返回int的函数。尝试

是合理的
Func<void, int>

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

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) {}

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

答案 2 :(得分:1)

由于您的功能不需要代理,因此需要int,您最好完全避开代理,只需传递int值,然后执行以下操作:< / p>

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

创建干净的高质量代码的一般想法是,一个函数接受执行特定任务所需的值,而不是一些更大的&#34;更大的复杂输入。那个。