在我们的实际开发中已经会遇到可空类型,而在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. Leetcode Elemination Game

    题目网址:https://leetcode.com/contest/2/problems/elimination-game/ 题意: 给定一个从1到n的数列,第一次从最左边开始,每隔一个淘汰一个数字. ...

  2. NOIP2016普及组

    普及组.代码有空发. 第一题就是买铅笔.暴力模拟绝对可取. 第二题就是回文日期.从t1的年份到t2的年份枚举每一年.头尾要特判. 第三题就是海港.骗了40分. 第四题就是魔法阵.不太好优化. 完.

  3. Android之ImageSwitcher

    要点: (查看Api总结) 1:ImageSwitcher 继承 ViewSwitcher, (ViewSwitcher 有继承FrameLayout ) 2: 要实现切图必须实现 ViewSwitc ...

  4. JS 传值 传址

    在JS中,有两种不同的方式可以操作数据的值,这两种技术分别叫做 传值 和 传址. 传值:在赋值过程中,首先对值进行了一份拷贝,而后将这份拷贝存储到一个变量.对象属性或数组元素中.拷贝的值和原始的值是完 ...

  5. Oracle直方图的详细解析

    yuanwen:http://blog.csdn.net/javacoffe/article/details/5578206 Oracle直方图解析 一.    何谓直方图: 直方图是一种统计学上的工 ...

  6. Groovy 处理 XML

    1. Parsing XML 1.1. XmlParser and XmlSlurper The most commonly used approach for parsing XML with Gr ...

  7. SVN使用总结

    ## 常用命令 建立分支 --- svn copy/cp svn cp http://example.com/repos/myproject/trunk http://example.com/repo ...

  8. Oracle 设置表空间自增长

    Oracle修改表空间大小 使用Oracle10g建立数据库后,向数据库中导入了部分数据,第二天继续向数据库中导入数据表时发生错误: 查了很多资料发现原来是Oracle表空间限制,导致无法继续导入数据 ...

  9. js库收集

    ------图表 中文 http://www.highcharts.me/ 英文 http://www.highcharts.com/ ------web前端开发框架 中文 http://www.bo ...

  10. 为什么LTE系统的最小时间单位是Ts?

    之前一直在做LTE物理层相关的工作,一直有个疑惑, 在36.211开头的一章定义Ts的大小是1/(15000*2048)s,为什么定义这么一个奇怪的unit time. 最近才反应过来,这跟FFT/I ...