8.1.2 在 C# 中把行为表示成函数

8.1.2 在 C# 中把行为表示成函数
我们前面提到过,以面向对象的方式理解函数,就是把它认为是有一个单独方法的接口。如果我们看一下清单 8.1 的代码,可以看到 IClientTest 就是这样声明的。这意味着,这个测试可以很容易地表示成一个简单的函数。在 C# 中,我们可以使用 lambda 函数来写测试:
Func isRiskyYearsInJob =
client => client.YearsInJob < 2;
不使用接口类型,现在,我们使用 Func,它表示一个函数,取 Client 作为参数值,并返回布尔值。通过以这种方式写代码,我们显著了减少样本代码的数量,围绕在表示测试的表达式外围的。
正如我们可以集合中存储对象,实现接口,我们也可以可以创建一个集合,存储函数值,在清单 8.2 中,你将看到,如何使用 List 类型来实现。注意,我们要创建一个完全标准的对象集合——我们可以遍历集合中的所有函数,或者,通过添加或删除某些函数值,来改变集合。
当初始化集合时,我们可以很容易地写代码,在一个单独的方法中,指定测试的默认集。我们可以使用 lambda 函数的语法,添加这些测试,而无需预先声明这些函数,也可以使用 C# 3.0 的功能,称为集合初始化器(collection initializer),使使语法更简洁。
Listing 8.2 Loan suitability tests using a list of functions (C#)
class Client {
public string Name { get; set; }
public int Income { get; set; }
public int YearsInJob { get; set; }
public bool UsesCreditCard { get; set; }
public bool CriminalRecord { get; set; }
}
static List> GetTests() {
return new List> {
client => client.CriminalRecord,
client => client.Income < 30000,
client => !client.UsesCreditCard,
client => client.YearsInJob < 2
};
}
清单 8.2 使用了许多C# 3.0 的新功能,由于这些功能,使之颇为类似于 F# 的实现。首先,我们声明一个类,来存储有关客户信息,使用自动属性。接下来,我们实现一个方法,返回测试的集合。方法的主体就是一个单独的 return 语句,创建 .NET 列表类型,并使用集合初始化器,初始化它的元素。可以用相同的方式,在创建集合时为数组指定的值。在这个外表之下,是调用集合的 Add 方法,但它是更清晰。
存储在集合中的值,是使用 lambda 函数语法写的函数。注意,我们不必指定 client 参数值的类型。这是因为,C# 编译器知道 Add 方法的参数值,是与泛型类型参数相同的,在我们的例子中,是 Func
注意
以行为为中心程序的一个经常要求,是从库中动态地加载新的行为的能力。对于我们的应用程序,将意味着,有人会写 .NET 类库,有包含
GetTests 方法的类型。这将返回测试列表,像早前的代码一样;我们的程序会调用这个方法,在执行时得到测试,并可以执行测试,而无需知道更多有关的内容。
这可以使用来自 System.Reflection 命名空间标准 .NET 类,来实现。典型的情况是动态加载程序集,找到这个程序集内的所有适当的类,并在运行时创建它们的实例。在本书的网站上可以找到有关使用反射的详细信息。
现在,我们有一个类来表示客户,和一个测试集合,建议我们是否向该客户提供贷款,让我们看看如何运行测试。
Tags: 

延伸阅读

最新评论

发表评论