C#匿名方法介绍Action、Func、柯里化Currying
在C#中,匿名方法是一种没有名称的方法,可以被用作委托的参数或者赋值给委托类型的变量。匿名方法主要有两种形式:匿名方法和lambda表达式。
一、匿名方法
匿名方法是C# 2.0引入的特性。匿名方法用delegate
关键字定义,它可以有参数,也可以没有参数。如下示例:
namespace niming_function
{
internal class Program
{
static void square2(int num)
{
int result = num * num;
Console.WriteLine(result);
}
static void Main(string[] args)
{
Console.WriteLine("匿名函数");
Action<int> square = delegate (int num)
{
int result = num * num;
Console.WriteLine(result);
};
square(3); // 输出:9
square2(3); // 输出:9
}
}
}
在这个示例中,我们创建了一个匿名方法square,该方法接受一个整数,计算它的平方,并将结果打印到控制台。然后我们将这个匿名方法赋值给Action<int>
类型的变量square
,并调用这个方法。匿名方法square等同于类成员方法square2,只是square是在方法里面定义的方法,写法和square2有差别。
Action的解释
在C#中,Action是一个委托(delegate)。它被用来表示一个没有返回值且可能带有任意数量参数的方法。这种方法被封装在一个 Action 委托实例中,然后可以像普通方法一样被调用。Action 委托可以带有类型参数,以此来定义参数的类型。
匿名函数是没有名字的方法或函数。它们常常被用作参数传递给其他方法,或者用来定义事件处理程序。在C#中,匿名函数常常通过Func和Action委托来表示。
总结:
Action表示的匿名方法没有返回值,Func表示的匿名方法有返回值。
接受两个int参数的Action委托的例子
Action<int, int> addAndPrint = (x, y) =>
{
int result = x + y;
Console.WriteLine(result);
};
addAndPrint(3, 5); // 输出 8
接受任意参数的Action委托的例子
Action<object[]> printAll = args =>
{
foreach (var arg in args)
{
Console.WriteLine(arg);
}
};
printAll(new object[] { "Hello, world!", 42, DateTime.Now });
Func的用法
//如果你的匿名函数有返回值,那么你应该使用 Func 委托而不是 Action 委托。
//Func 委托用来表示有返回值的函数,最后一个类型参数表示返回类型。
Func<int, int, int> addFunc = (x, y) => x + y;
int result = addFunc(3, 5);
Console.WriteLine(result); // 输出 8
在上述例子中,addFunc 是一个 Func 委托,它接受两个 int 类型的参数并返回一个 int 类型的结果。这个委托被指定了一个匿名函数,即 (x, y) => x + y,这个匿名函数接受两个参数并返回它们的和。
需要注意的是,Action 和 Func 委托都可以接受类型参数来指定参数的类型,但 Func 委托的最后一个类型参数总是用来表示返回类型的。Action 委托则没有返回值。
全部代码如下:
namespace niming_function
{
internal class Program
{
static void square2(int num)
{
int result = num * num;
Console.WriteLine(result);
}
static void Main(string[] args)
{
Console.WriteLine("匿名函数");
Action<int> square = delegate (int num)
{
int result = num * num;
Console.WriteLine(result);
};
square(3); // 输出:9
square2(3); // 输出:9
// 下是一个接受两个int参数的Action委托的例子
Action<int, int> addAndPrint = (x, y) =>
{
int result = x + y;
Console.WriteLine(result);
};
addAndPrint(3, 5); // 输出 8
// 下是一个接受任意参数的Action委托的例子
Action<object[]> printAll = args =>
{
foreach (var arg in args)
{
Console.WriteLine(arg);
}
};
printAll(new object[] { "Hello, world!", 42, DateTime.Now });
//如果你的匿名函数有返回值,那么你应该使用 Func 委托而不是 Action 委托。
//Func 委托用来表示有返回值的函数,最后一个类型参数表示返回类型。
Func<int, int, int> addFunc = (x, y) => x + y;
int result = addFunc(3, 5);
Console.WriteLine(result); // 输出 8
}
}
}
运行结果如下:
匿名函数
9
9
8
Hello, world!
42
2023/11/17 21:00:14
8
二、Lambda 表达式
Lambda 表达式是C# 3.0引入的特性,它提供了一种更简洁的方式来写匿名方法。Lambda表达式有两种形式:表达式Lambda和语句Lambda。如下示例:
// 表达式 Lambda
Func<int, int> squareExpression = num => num * num;
Console.WriteLine(squareExpression(5)); // 输出:25
// 语句 Lambda
Action<int> squareStatement = num =>
{
int result = num * num;
Console.WriteLine(result);
};
squareStatement(5); // 输出:25
在这个示例中,我们使用Lambda表达式创建了两个匿名方法,它们都接受一个整数,计算它的平方,并将结果打印到控制台。然后我们将这些匿名方法分别赋值给Func<int, int>
和Action<int>
类型的变量,并调用这些方法。
总的来说,匿名方法提供了一种方便的方式来创建和使用小的、简单的方法,而不需要定义一个完整的方法。
三、柯里化
"柯里化"是一种编程技术,由 Haskell Curry 提出,因此得名。它是将一个带有多个参数的函数转变为一系列使用一个参数的函数的过程。例如,一个接受三个参数的函数f(x, y, z)可以被柯里化为f(x)(y)(z)。这种技术在函数式编程中非常常见,可以让你创建更灵活的函数,以及支持部分应用(partial application)和函数组合(function composition)等高级功能。
在 C# 中,你可以使用 Func 委托来实现柯里化。以下是一个三元函数柯里化的示例:
using System;
public static class CurryExtensions
{
public static Func<T1, Func<T2, Func<T3, TResult>>> Curry<T1, T2, T3, TResult>(
this Func<T1, T2, T3, TResult> func)
{
return a => b => c => func(a, b, c);
}
}
class Program
{
static void Main()
{
Func<int, int, int, int> addThreeNumbers = (x, y, z) => x + y + z;
var curriedAdd = addThreeNumbers.Curry();
var addFiveAndSix = curriedAdd(5)(6);
Console.WriteLine(addFiveAndSix(7)); // Prints 18
}
}
在这个示例中,CurryExtensions
类定义了一个扩展方法 Curry
,它接收一个三元函数并返回一个柯里化的函数。然后,我们在 Main
方法中创建了一个 addThreeNumbers
函数,并将其柯里化。最后,我们调用柯里化的函数并打印结果。
这种技术的优点是它允许你创建更灵活的函数,并进行部分应用。例如,如果你有一个需要三个参数的函数,但你只有两个参数,你可以部分应用这个函数,返回一个新的函数,只需要一个参数就可以完成计算。这种技术在函数式编程中非常有用,因为它可以让你创建更复杂、更强大的函数。