本文又可以看作对 TryParse、 Nullable 和 Tuple 的比较。

本文大部分内容参考自《深入理解 C#》 4.4.1 尝试一个不使用输出参数的操作。

TryParse

C# 从 2.0 就引入了 TrySomething + out 参数的模式,比如 Dictionary 的 TryGetValue 和许多用于解析数据的 TryParse。

该模式的核心在于 TrySomething 的返回值用于表示 Something 是否成功,然后具体结果通过 out 参数传出。

随着 C# 的版本更新,TrySomething 模式逐渐普及,C# 程序员们在编写自己的代码时也经常使用该模式。但 TrySomething 的一个弊端也很明显 —— 方法的返回值居然不是最重要的。

TyrParse 示例:

  1. var text = "456";
  2. if (int.TryParse(text, out int num))
  3. {
  4. Console.WriteLine($"num: {num}");
  5. }
  6. else
  7. {
  8. Console.WriteLine("Parse failed!");
  9. }

Nullable

Nullable 模式的核心在于将 Nullable 作为方法的返回值传出。

Nullable 将自然的返回值和解析是否成功封装在一个变量中。其次,它还将“做 Something”和“测试”这两个步骤分开了。这样才做到了条理清晰、重点突出。

尤其是在有很多方法参数的情况下,输出参数变得更难发现(更难引起重视),而使用 Nullable 作为方法返回值时,编写代码和阅读代码的人都能在第一时间意识到方法的核心功能是什么。

Nullalbe 示例:

  1. static void Main(string[] args)
  2. {
  3. var text = "Not a number";
  4. int? parsed = TryParse(text);
  5. if (parsed.HasValue)
  6. {
  7. Console.WriteLine($"Parsed to {parsed.Value}");
  8. }
  9. else
  10. {
  11. Console.WriteLine("Coundn't parse");
  12. }
  13. }
  14. static int? TryParse(string text)
  15. {
  16. int ret;
  17. if (int.TryParse(text, out ret))
  18. {
  19. return ret;
  20. }
  21. return null;
  22. }

Tuple

随 .NET Framework 4.0 推出的 Tuple 有时比 Nullable 更加好用。

  1. Tuple 用起来比 int? 更整洁一些
  2. 还可以添加额外信息,例如 Tuple 的最后一个元素可以用于存储解析失败的原因

Tuple 示例:

  1. static void Main(string[] args)
  2. {
  3. var text = "Not a number";
  4. var parsed = TryParse(text);
  5. if (parsed.Item2)
  6. {
  7. Console.WriteLine($"Parsed to {parsed.Item1}");
  8. }
  9. else
  10. {
  11. Console.WriteLine(parsed.Item3);
  12. }
  13. }
  14. static Tuple<int, bool, string> TryParse(string text)
  15. {
  16. if (int.TryParse(text, out int num))
  17. {
  18. return Tuple.Create(num, true, "");
  19. }
  20. return Tuple.Create(0, false, $"Coundn't parse \"{text}\"");
  21. }