第四章 诚实函数、null 与 Option

诚实函数

诚实函数,我更愿意称其为: 可靠函数

诚实函数:

  • 代码即文档,名称就是行为
  • 健壮性强

// 非诚实函数
public static int Divide(int numerator, int denominator)
{
return numerator / denominator;
}

//诚实函数
public static int? Divide(int numerator, int denominator)
{
if(denominator == 0) return null;
return numerator / denominator;
}

null

破坏代码健壮性的一大元凶就是null

我们有一些方法来解决这个问题

解决null的最终兵器:Option 类型

Option 类型的值有两种可能:

  • Some(value):表示确实有值。
  • None(或 null 的替代):表示值缺失。

Option类型示例

public abstract class Option<T>
{
public sealed class Some : Option<T>
{
public T Value { get; }
public Some(T value) => Value = value;
}

public sealed class None : Option<T> { }

public static Option<T> Create(T value) =>
value == null ? new None() : new Some(value);
}

为什么使用 Option 而不是 null?

  1. 强制处理缺失的值:无法忽视null,编译器会提醒必须处理 None
  2. 增强语义
  3. 更少的异常

真实案例:

  • Web API:返回一个用户信息时,用 Option<User> 取代直接返回 User?
  • 银行系统
  • 链式调用:Option 可与 LINQ 风格链式调用很好地结合,简化处理逻辑。

永远不会诚实的c#

我们可以在编写代码时让函数尽量诚实,但c#在语言层面就让函数永远无法达到所谓”诚实”的真实.

  • 性能 vs 安全性
    C# 同时提供了面向性能的低层特性和面向安全性的高层特性。为了满足性能需求,开发者有时不得不偏离“完全诚实”的语言结构,比如使用 unsafe 代码或绕过类型检查。
  • 异常机制的局限性
    C# 目前的异常系统几乎让真正诚实的函数变得不可能实现。为什么?因为几乎任何方法都可能抛出 OutOfMemoryException 或其他运行时异常。
    即使你完全控制了自己的代码逻辑,也不要忘记:真正控制执行的是 CLR(Common Language Runtime) 。它有能力在任何时候干预你的程序运行,抛出你意想不到的异常。

Exercises