问题在于“null”这个词。这是什么意思? null 可能意味着该值无法确定,引发了异常,仅仅是该值为 null 或其他一些上下文含义。您的问题就是一个很好的例子,因为您自己在任意声明,在您看来,null 表示字符串解析失败。
Microsoft 的 TryParse 范例很棒,但用途有限。考虑以下场景:
- 字符串 == "89"
- 字符串 == 空
- string == "Hello World"
- 字符串 == ""
- 字符串 == "2147483650"
然而,您唯一的选择是将 Integer 或 Null 分配给您的输出,并返回 true 或 false。
假设它有效,您将如何处理这些信息?像这样?
int? value = null;
if (int.TryParse(Session["Key"].ToString(), out value)) {
if (value == null)
// Handle "Appropriate" null
else
// Handle appropriate numeric value
}
else {
// Note: value == null here, and TryParse failed
// Handle null...
// What if the reason it failed was because the number was too big?
// What if the string was Empty and you wanted to do something special?
// What if the string was actually junk? Like "(423)322-9876" ?
// Long-Story Short: You don't know what to do here without more info.
}
考虑这个 NullableInt TryParse 示例:
public bool TryParseNullableInt(string input, out int? output)
{
int tempOutput;
output = null;
if (input == null) return true;
if (input == string.Empty) return true; // Would you rather this be 0?
if (!int.TryParse(input, out tempOutput))
return false; // What if string was "2147483650"... or "Twenty Three"?
output = tempOutput;
return true;
}
一种解决方案是使用枚举 TryParse 而不是布尔 TryParse:
public ParseStatus TryParseNullableInt(string input, out int? output)
{
int tempInteger;
output = null;
if (input == null) return ParseStatus.Success;
if (input == string.Empty) { output = 0; return ParseStatus.Derived; }
if (!int.TryParse(input, out tempInteger)) {
if (ParseWords(input, out tempInteger)) { // "Twenty Three" = 23
output = tempInteger;
return ParseStatus.Derived;
}
long tempLong;
if (long.TryParse(input, out tempLong))
return ParseStatus.OutOfRange;
return ParseStatus.NotParsable;
}
output = tempInteger;
return ParseStatus.Success;
}
另一个问题是out 变量的存在。您的第三个选择是使用描述性单子,如下所示:
public Maybe<int?> TryParseNullableInt(string input)
{
if (input == null) return Maybe.Success(null);
if (input == string.Empty) { return Maybe.Derived(0); }
int tempInteger;
if (!int.TryParse(input, out tempInteger)) {
if (ParseWords(input, out tempInteger)) { // "Twenty Three" = 23
return Maybe.Derived(tempInteger);
}
long tempLong;
if (long.TryParse(input, out tempLong))
return Maybe.OutOfRange();
return Maybe.NotParsable();
}
return Maybe.Success(tempInteger);
}
您可以将 Monad 用作单枚举值,或者像这样:
Maybe<int?> result = TryParseNullableInt("Hello");
if (result.HasValue) {
if (result.Status == ParseStatus.Success)
// Do something you want...
else if (result.Status == ParseStatus.Derived)
// Do something else... more carefully maybe?
}
else if (result.Status == ParseStatus.OutOfRange)
MessageUser("That number is too big or too small");
else if (result.Status == ParseStatus.NotParsable)
// Do something
使用 Monads 和可能的枚举 TryParses,您现在可以从描述性返回中获得所需的所有信息,并且没有人需要猜测 null 可能意味着什么。