没有返回类型的函数委托

Posted

技术标签:

【中文标题】没有返回类型的函数委托【英文标题】:Func delegate with no return type 【发布时间】:2010-10-29 09:18:38 【问题描述】:

所有 Func 委托都返回一个值。可以与返回 void 的方法一起使用的 .NET 委托有哪些?

【问题讨论】:

【参考方案1】:

所有 Func 委托都返回一些东西;所有的 Action 委托都返回 void。

Func<TResult> 不接受任何参数并返回 TResult:

public delegate TResult Func<TResult>()

Action&lt;T&gt; 接受一个参数并且不返回值:

public delegate void Action<T>(T obj)

Action 是最简单的“裸”委托:

public delegate void Action()

还有Func&lt;TArg1, TResult&gt;Action&lt;TArg1, TArg2&gt;(以及其他最多16 个参数)。所有这些(Action&lt;T&gt; 除外)都是 .NET 3.5 的新内容(在 System.Core 中定义)。

【讨论】:

仅供参考,下一个版本的基类库将包括支持四个以上形式参数的 Func 和 Action 类型。我不记得它们到底有多大。 实际上,在 4.0 中它们似乎上升到 16 个。 1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, ... 这清楚地表明编译器需要能够在某些时候处理more arguments to a function than it currently does未来! 其实 Tustin2121 是对的,他们在 .NET 4.0 中增加了 16 个参数(在Func&lt;,,, ... ,&gt; 的情况下加上一个返回类型),但是每个“系列”的最后八种类型都定义了在System.Core.dll,而不是mscorlib.dll,所以这就是michielvoo 没有看到它们的原因。但是,.NET 版本 4.5 和 4.5.1 中不再添加 Funcs 或 Actions。这个序列会变成A170836 还是A170875?请继续关注。 为方便起见,我提供了一些带有多个参数的重载,但有一点,只需将您的参数包装在一个对象中......【参考方案2】:

... 不带参数并且返回类型为 void?

我相信Action 可以解决这个问题。

【讨论】:

【参考方案3】:

所有的 Func 委托都至少有一个参数

那不是真的。它们都至少采用一个类型参数,但该参数决定了返回类型。

所以Func&lt;T&gt; 不接受任何参数并返回一个值。当您不想返回值时,请使用 ActionAction&lt;T&gt;

【讨论】:

【参考方案4】:

试试System.Func&lt;T&gt;System.Action

【讨论】:

不过,我认为 .Net 2.0 中不存在 0 arg 之类的东西。 很奇怪:Func 在 .Net 2.0 中根本不存在,尽管 Predicate 和 Action 存在。 对于 .NET 2.0 使用 MethodInvoker 委托。 .NET 2 也有(或有)一个委托类型Converter&lt;TInput, TOutput&gt;,类似于后来的Func&lt;T, TResult&gt;。它在List&lt;&gt;.ConvertAll 方法中使用,该方法将List&lt;&gt; 中的每个元素投影到另一个对象上,并将所有“函数值”放在新的List&lt;&gt; 中。 (后来,人们经常会为此使用 Linq Select。)【参考方案5】:

调用返回值和非返回值子例程的一种非常简单的方法。分别使用 FuncAction(另见https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx)

试试这个例子

using System;

public class Program

    private Func<string,string> FunctionPTR = null;  
    private Func<string,string, string> FunctionPTR1 = null;  
    private Action<object> ProcedurePTR = null; 



    private string Display(string message)  
      
        Console.WriteLine(message);  
        return null;  
      

    private string Display(string message1,string message2)  
      
        Console.WriteLine(message1);  
        Console.WriteLine(message2);  
        return null;  
      

    public void ObjectProcess(object param)
    
        if (param == null)
        
            throw new ArgumentNullException("Parameter is null or missing");
        
        else 
        
            Console.WriteLine("Object is valid");
        
    


    public void Main(string[] args)  
      
        FunctionPTR = Display;  
        FunctionPTR1= Display;  
        ProcedurePTR = ObjectProcess;
        FunctionPTR("Welcome to function pointer sample.");  
        FunctionPTR1("Welcome","This is function pointer sample");   
        ProcedurePTR(new object());
      

【讨论】:

感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation would greatly improve its long-term value 通过展示为什么这是一个很好的解决问题的方法,并将使其对未来有其他类似问题的读者更有用。请edit您的回答添加一些解释,包括您所做的假设。【参考方案6】:

有时您会想要为事件处理编写一个委托,在这种情况下,您可以利用System.EvenHandler&lt;T&gt;,它隐式接受object 类型的参数以及应该从EventArgs 派生的第二个参数。 EventHandlers 将返回void

我个人在测试过程中发现这对在函数体中创建一次性回调很有用。

【讨论】:

【参考方案7】:

... 不带参数并且返回类型为 void?

如果你写的是System.Windows.Forms,你也可以使用:

public delegate void MethodInvoker()

【讨论】:

以上是关于没有返回类型的函数委托的主要内容,如果未能解决你的问题,请参考以下文章

C#控制台基础 返回类型为void的 int 类型 参数委托与匿名函数

委托泛型委托多播委托匿名函数lamda表达式事件

CLR via C# 笔记 -- 委托(17)

Unity基础(26)-委托使用

163-委托的定义和声明

C#委托