C#系统委托之Action And Func

  1. Action
  2. Action<T>
  3. Func
  4. Func<T>

 

Action:封装一个方法,该方法不具有参数并且不返回值

public delegate void Action()

 Action<T>:Action的泛型实现了1到16个传入参数的定义,但是仍然没有返回值,得出结论Action不支持返回值,如果需要返回值请使用另一个系统委托Func

public delegate void Action<in T>(T obj)
...
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(
	T1 arg1,
	T2 arg2,
	T3 arg3,
	T4 arg4,
	T5 arg5,
	T6 arg6,
	T7 arg7,
	T8 arg8,
	T9 arg9,
	T10 arg10,
	T11 arg11,
	T12 arg12,
	T13 arg13,
	T14 arg14,
	T15 arg15,
	T16 arg16
)

 由此可见Action的定义非常简单,但是这样的委托实在是太常用了,如果用一次自己定义一个也是可以的,多的话就感觉重复劳动太多:

过去自定义委托:

using System;
using System.Windows.Forms;

public delegate void ShowValue();

public class Name
{
   private string instanceName;

   public Name(string name)
   {
      this.instanceName = name;
   }

   public void DisplayToConsole()
   {
      Console.WriteLine(this.instanceName);
   }

   public void DisplayToWindow()
   {
      MessageBox.Show(this.instanceName);
   }
}

public class testTestDelegate
{
   public static void Main()
   {
      Name testName = new Name("Koani");
      ShowValue showMethod = testName.DisplayToWindow;
      showMethod();
   }
}
View Code

现在直接使用Action:

using System;
using System.Windows.Forms;

public class Name
{
   private string instanceName;

   public Name(string name)
   {
      this.instanceName = name;
   }

   public void DisplayToConsole()
   {
      Console.WriteLine(this.instanceName);
   }

   public void DisplayToWindow()
   {
      MessageBox.Show(this.instanceName);
   }
}

public class testTestDelegate
{
   public static void Main()
   {
      Name testName = new Name("Koani");
      Action showMethod = testName.DisplayToWindow;
      //将 Action 委托与匿名方法一起使用
     // Action showMethod = delegate() { testName.DisplayToWindow();} ;
      //将 lambda 表达式分配给 Action 委托实例
      //Action showMethod = () => testName.DisplayToWindow();
      showMethod();
   }
}
View Code

  Action<T>的使用也是类似的,但是 Action<T>的定义是比较特别的,它有一个关键词In,In是用来干嘛的呢,按照MSDN的解释:


 

关于派生程度更小或更低的类型等相关的概念理解我推荐深入理解 C# 协变和逆变

Func:封装一个不具有参数但却返回 TResult 参数指定的类型值的方法

public delegate TResult Func<out TResult>()

Func<T>: Func的泛型同样的实现了1到16个传入参数,而且支持返回值

public delegate TResult Func<in T, out TResult>(
    T arg
)
...
public delegate void Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>(
    T1 arg1,
    T2 arg2,
    T3 arg3,
    T4 arg4,
    T5 arg5,
    T6 arg6,
    T7 arg7,
    T8 arg8,
    T9 arg9,
    T10 arg10,
    T11 arg11,
    T12 arg12,
    T13 arg13,
    T14 arg14,
    T15 arg15,
    T16 arg16
)

 

Func的定义同样简单明了,和Action一样是为了简化代码方便”客户“使用:

过去自定义委托:

using System;
using System.IO;

delegate bool WriteMethod();

public class TestDelegate
{
   public static void Main()
   {
      OutputTarget output = new OutputTarget();
      WriteMethod methodCall = output.SendToFile;
      if (methodCall())
         Console.WriteLine("Success!"); 
      else
         Console.WriteLine("File write operation failed.");
   }
}

public class OutputTarget
{
   public bool SendToFile()
   {
      try
      {
         string fn = Path.GetTempFileName();
         StreamWriter sw = new StreamWriter(fn);
         sw.WriteLine("Hello, World!");
         sw.Close();
         return true;
      }  
      catch
      {
         return false;
      }
   }
}
View Code

 

现在直接使用Func:

using System;
using System.IO;

public class TestDelegate
{
   public static void Main()
   {
      OutputTarget output = new OutputTarget();
      Func<bool> methodCall = output.SendToFile;
     //Func<bool> methodCall = delegate() { return output.SendToFile(); };将 Func<TResult> 委托与匿名方法一起使用
     // Func<bool> methodCall = () => output.SendToFile(); 将 lambda 表达式分配给 Func<T, TResult> 委托
      if (methodCall())
         Console.WriteLine("Success!"); 
      else
         Console.WriteLine("File write operation failed.");
   }
}

public class OutputTarget
{
   public bool SendToFile()
   {
      try
      {
         string fn = Path.GetTempFileName();
         StreamWriter sw = new StreamWriter(fn);
         sw.WriteLine("Hello, World!");
         sw.Close();
         return true;
      }  
      catch
      {
         return false;
      }
   }
}
View Code

 

 

通过定义可以看到Func的定义不仅可以看到In关键词的身影,还有一个Out关键词,MSDN的解释如下(Out作为方法的输出参数也是经常用到的):

 


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CLR
{
    public class Employee
    {

    }
    class Program
    {
        static void Main(string[] args)
        {
            Employee emp = new Employee();
            object obj = emp;

            IList<Employee> emplist = new List<Employee>();

            // List<object> objlist = emplist;

            IList<object> objlist1 = emplist.Select(o => (object)o).ToList(); ;
            //因为Ilist的泛型参数T没有使用Out关键词标识,所以在给方法Add1直接传递 IList<Employee>类型的参数时会有无效参数提示
            Add1(emplist);
            //间接的使用方法是像上面那样逐个转换
            Add1(objlist1);


            IEnumerable<Employee> empenum = new List<Employee>();
            IEnumerable<object> objenum = empenum;

            Add(empenum);
            Add(objenum);

            Console.ReadKey();
        }
        private static void Add(IEnumerable<object> enums)
        {

        }

        private static void Add1(IList<object> enums)
        {

        }
    }
}

 

关于派生程度更大或更高的类型等相关的概念理解我依然推荐深入理解 C# 协变和逆变

 

posted @ 2014-10-19 17:46  麻将我会  阅读(3675)  评论(2编辑  收藏  举报