3.3.3 C# 中的函数式列表

728 篇文章 1 订阅
349 篇文章 0 订阅

3.3.3 C# 中的函数式列表

 

要了解函数式列表类型的工作原理,最好的办法是看看如何用 C# 实现同样的功能。有几种方法来表达列表可能为空,或者有头和尾。面向对象的解决方案可能是写一个抽象类 FuncList,它有两个派生类,比如,EmptyList<T> 和 ConsCellList<T>,分别表示种情况。为使代码尽可能简单,我们只使用一个类,有一个属性 IsEmpty,它会告诉我们这个实例是否包含值。注意, FuncList <T> 类型的每个实例至多包含一个值。当这个实例表示空列表时,它不包含任何值;当它是 cons cell 时,只保存一个值。清单 3.14 显示了这个实现。

 

清单 3.14 函数式列表 (C#)

public class FuncList {

 public FuncList() {    [1]

   IsEmpty = true;

  }

 public FuncList(T head, FuncList tail) { [2]

   IsEmpty = false;

   Head = head;

   Tail = tail;

  }

 public bool IsEmpty { get; private set; }  <-- 表示列表是否为空

 public T Head { get; private set; }     | 保存cons cell 的属性

 public FuncList Tail { get; private set; }  |

}

public static class FuncList {      [3]

 public static FuncList Empty() {

   return new FuncList();

  }

 public static FuncList Cons(T head, FuncList tail) {

   return new FuncList(head, tail);

  }

}

 

FuncList<T> 类是一个泛型的 C# 类,因此,它可以保存任何类型的值。它有一个属性 IsEmpty,当我们用无参数的构造函数创建空的列表时,它被设置为 true[1];第二个构造函数有两个参数,能创建 cons cell,IsEmpty 被设置为 false。第一个参数(head)是将要保存在 cons cell 中的值,第二个参数(tail)是将要创建的 cons cell 的后继列表。列表尾的类型与创建的列表的类型相同,写作 FuncList<T>。第一个构造函数对应于 F# 空列表(写作 []),第二个构造函数创建 cons cell,与双冒号运算符(head::tail)的方法相同。

我们已经知道,函数式列表是不可变的,因此,类的所有属性都是只读的。我们使用 C# 3.0 的自动属性(automatic properties)功能,实现所有属性,它生成了 getter 和 setter 属性,但我们应该指定 setter 为私有,使之不能从外面修改。要使类型真正只读,只能在构造函数中设置属性的值,这样,列表单元一经创建,就没有属性能够进行修改。事实上,有很多不同的实现策略来声明不可变类型,这就说明,不可变性的概念,可以有不同的使用方法,不是一种语言功能。使用自动属性,语法更简洁,但也失去了当使用标记为 readonly 的字段时, C# 编译器能做的检查,只能是一种权衡。

正如在前面的元组示例中,我们引入了一个非泛型的工具类 FuncList [3],有一些静态方法,能够简化泛型列表的创建,提供的方法包括创建空列表(Empty)和 cons cell (Cons)。使用这个类的好处是,C# 可以推断方法调用的参数类型,这样,如果有明显的上下文,我们不必指定列表中的值的类型。现在,我们已用 C# 实现了列表,就可以写代码,使用列表来执行计算了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值