许多实际的扩展可以通过扩展方法来实现,并非所有实际的扩展都有可以扩展的类型。对于某些场景,简单的静态方法比较适合。为了更容易调用这些方法,可以使用 using static 声明除去类名。.
例如,如果打开了 System.Console
using static System.Console;
可以把下面的代码
Console.WriteLine("Hello World!");
改为
WriteLine("Hello World!");
在使用此声明之后,就可以使用类 Console 的所有静态成员,如 WriteLine、Write、ReadLine、Read、Beep 等,而不需要编写 Console 类。只需要确保在打开其他类的静态成员时不要陷入冲突,或者在使用静态方法时不要使用基类的方法。
下面看一个实际的例子。高阶函数以函数作为参数,或者返回一个函数,或者返回两个函数。在处理函数时,可以将两个函数合并到一个函数中。
为此可以使用Compose 方法,如下面的代码片段所示:
public static class FunctionalExtensions
{
//...
public static Func<T1, TResult> Compose<T1, T2, TResult>(
Func<T1, T2> fl, Func<T2, TResult> f2) =>
a => f2(f1(a));
}
要使用 Compose 方法,首先创建两个委托 f1 和 f2,在输入中添加 1 或 2。这些委托会与 Compose 方法相结合。由于 usingstatic 声明打开了类 FunctionalExtensions 的静态成员,所以可以不使用类名来调用 Compose 方法。在使用 Compose 方法创建 f3之后,就调用 f3 方法:
using System;
using static System.Console;
using static UsingStatic.FunctionalExtensions;
namespace UsingStatic
{
class Program
{
static void Main()
{
//...
Func<int, int> f1 = x => x + 1;
Func<int, int> f2 = x => x + 2;
Func<int, int> f3 = Compose(f1, f2);
var xl = f3(39);
WriteLine(x1);
//...
}
}
}
写入控制台的结果当然是 42。
声明 Compose 方法时,参数类型可以在输入和输出之间有所不同。在下面的代码片段中,传递给 Compose 方法的第一个方法接收一个字符串,并返回 Person 对象;第二个方法接收 Person 并返回一个字符串。如果编译器不能从变量和返回类型中识别参数类型,就必须指定具体的委托类型,方法是接收字符串并返回一个 Person。只有变量名,并不能帮助编译器确定它的类型。通过传递给 Compose 方法的第二个方法,显然,输入的类型与第一个方法返回的类型相同,因此不需要指定类型。在调用Compose 方法之后,变量 greetPerson 是两个输入方法的组合:
var greetPerson = Compose(
new Func<string, Person>(name => new Person(name)),
person => $"Hello, {person.FirstName}");
WriteLine(greetPerson("Mario Andretti"));
在WriteLine 方法中使用字符串 Mario Andretti 调用greetPerson 方法将字符串 Hello,Mario 写入控制台。