在我们的实际开发中已经会遇到可空类型,而在C#中自从2.0之后就提供了可空类型(Nullable<T>),普通的值类型是不可以赋值为NULL,但是在类型的后面加上问号就变成了可空类型,这样就可以赋值为NULL了。当然这样的方式也可以用于函数式编程中,但函数式编程有自己的独特方式来解决这种问题,今天我们将围绕这个问题,虽然篇幅比较少,但也请读者可以阅读完。

我们当然不能改变语言的设计,所以我们只能使用现有的来实现可选值。这里我们利用类来实现,下面是Option<T>初期的代码:

         public sealed class Option<T>
{
private readonly T value;
public T Value
{
get
{
return value;
}
} private readonly bool hasValue;
public bool HasValue { get { return hasValue; } }
public bool IsSome { get { return hasValue; } }
public bool IsNone { get { return !hasValue; } } public Option(T value)
{
this.value = value;
this.hasValue = true;
} private Option() { }
public static readonly Option<T> None = new Option<T>();
}

这样我们就可以利用这个类来实现和可空类型一样的效果,比如下面这段代码:

             var p1 = new Option<int>();
var p2 = Option<int>.None;
if (p1.HasValue) // 等价于 x != null
{ }

我们可以看到在实例化Option的时候还需要传递类型参数,这里我们可以通过一个技巧来避免输入类型参数,而依赖于类型推断,这里我们写个辅助类:

         public sealed class Option
{
public static Option<T> Some<T>(T value)
{
return new Option<T>(value);
}
}

其实我们只是利用了一个泛型方法来创建这个实例就可以了,下面我们看看下面的示例:

         static void Main(string[] args)
{
var p1 = Option.Some();
var p2 = Option.Some();
if (p1 == p2)
{
Console.WriteLine("Y");
}
Console.ReadKey();
}

这里我们看到Option.Some节省了一些功夫,但是读者如果运行上面这个例子会发现,“Y”并不会输出到控制台中,但是我们可以看到10本来就应该等于10。因为这里我们对比的是Option<T>类型,并且p1和p2是两个不同的Option<T>所以我们还需要加以改善,下面我们重载操作符(在Option<T>类中继续追加):

             public static bool operator ==(Option<T> a, Option<T> b)
{
return a.HasValue == b.HasValue && EqualityComparer<T>.Default.Equals(a.Value, b.Value);
}
public static bool operator !=(Option<T> a, Option<T> b)
{
return !(a == b);
} public override int GetHashCode()
{
int hashCode = hasValue.GetHashCode();
if (hasValue)
hashCode ^= value.GetHashCode();
return hashCode;
}

这里我们通过重载“==”判断其中的Value,这样就可以解决上面的问题了。但是我们还有一个问题没有解决,就是在使用None的时候还需要传递类型参数,这里我们依然需要使用一个技巧来避免(在Option类中继续追加):

public static readonly Option None = new Option();

仅仅这样还不足够,因为Option无法转换成Option<T>类型所以我们还需要对Option<T>增加 功能,能够隐式的将Option转换成对应的Option<T>类型,下面是针对的代码(在Option<T>中增加):

             public static implicit operator Option<T>(Option option)
{
return Option<T>.None;
}

这样我们就可以直接将Option与Option<T>进行对比了,到这里我们就完成了我们自己的可选值的实现,在具体的项目中是使用可空类型还是可选值完全可以根据你个人的喜好,笔者建议使用本节介绍的可选值。

C#函数式编程之可选值的更多相关文章

  1. Scala - 快速学习08 - 函数式编程:高阶函数

    函数式编程的崛起 函数式编程中的“值不可变性”避免了对公共的可变状态进行同步访问控制的复杂问题,能够较好满足分布式并行编程的需求,适应大数据时代的到来. 函数是第一等公民 可以作为实参传递给另外一个函 ...

  2. javascript - Underscore 与 函数式编程

    <Javascript函数式编程 PDF> # csdn下载地址http://download.csdn.net/detail/tssxm/9713727 Underscore # git ...

  3. java8函数式编程实例

    什么是函数式编程 函数式编程是java8的一大特色,也就是将函数作为一个参数传递给指定方法.别人传的要么是基本数据类型,要么就是地址引用 ,我们要穿一个“动作”. Stream 说到函数式编程,就不得 ...

  4. C#函数式编程之惰性求值

    惰性求值 在开始介绍今天要讲的知识之前,我们想要理解严格求值策略和非严格求值策略之间的区别,这样我们才能够深有体会的明白为什么需要利用这个技术.首先需要说明的是C#语言小部分采用了非严格求值策略,大部 ...

  5. day03 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  6. 用C++进行函数式编程

    http://www.programmer.com.cn/12717/   文 / John Carmack 译 / 王江平 <Quake>作者Carmack认为追求函数式的程序设计有着实 ...

  7. Python进阶:函数式编程实例(附代码)

    Python进阶:函数式编程实例(附代码) 上篇文章"几个小例子告诉你, 一行Python代码能干哪些事 -- 知乎专栏"中用到了一些列表解析.生成器.map.filter.lam ...

  8. Python核心编程读笔 10:函数和函数式编程

    第11章 函数和函数式编程 一 调用函数  1 关键字参数 def foo(x): foo_suite # presumably does some processing with 'x' 标准调用 ...

  9. 《JS权威指南学习总结--8.8 函数式编程和8.8.1使用函数处理数组》

    内容要点:    和Lisp.Haskell不同,JS并非函数式编程语言,但在JS中可以像操控对象一样操控函数,   也就是说可以在JS中应用函数式编程技术.ES5中的数组方法(诸如map()和red ...

随机推荐

  1. 准备开发一款开源NES模拟器

    前几天无意见看到一些NES的开发资料,勾起了小时候暑假的无数美好回忆,做为一名码农,萌发了自己写一款模拟器的想法.一来可以加深自己对整个系统/游戏的理解,一来可以实现小时候的梦想:),希望可以坚持下来 ...

  2. mysql修改为utf8格式

    1.修改相应数据库的编码格式: -- 修改数据库编码为utf8 ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_general_ ...

  3. Yii2 中禁用csrf校验

    Yii2 默认开启csrf校验,但是有些时候确实不需要校验,比如对外提供API 一般做法直接在xxController中增加属性: public $enableCsrfValidation = fal ...

  4. Windows cmd命令搜索顺序

    一.在cmd中执行一个不带后缀的命令(不带路径),首先会在无后缀的系统命令(如cd.dir等)中搜索,如果找到了就执行该命令, (dir是无后缀的系统命令所以优先执行,无视当前目录中的dir.exe) ...

  5. ip地址合法性

    /* * Java语法上正则化表达式的使用技巧,对于'.'要用'\\.' (2)注意空字符串“”和null的区别,判断一个字符串是不是空字符串用.equals("") * (1,判 ...

  6. Rails中的content_tag与concat用法,可以连接任意html元素

    想输出如下html <% if user.present? %> <li> <a href="<%= user_info_url(user.id) %&g ...

  7. WCF 套接字连接已中止。这可能是由于处理消息时出错或远程主机超过接收超时或者潜在的网络资源问题导致的

    一个项目需要用到推送的功能,就是服务器主动推送数据给多台客户机.于是采用了WCF的双工通讯netTcpBinding 写好的项目,在本机测试都没有问题. 如果放在局域网内测试,问题出来了:先是安全性问 ...

  8. python核心编程笔记

    1.python的对象是通过引用传递的. 2.多元赋值: x, y = y, x

  9. PHP二维数组排序

    $arrays   要排序的数组 $sort_key 根据排序的key $sort_order 升序降序    SORT_ASC/SORT_DESC $sort_type 排序key类型 SORT_N ...

  10. Raab判别法确定级数是否收敛