短路 If 条件不起作用
Short-Circuit If Condition Does not work
我有一个抛出 NullReferenceException 的代码段。代码段是这样的
if (string.IsNullOrWhiteSpace(user.FirstName) && !(user.FirstName.Length <= 64))
{
// Some Code
}
这里的 if 条件首先应该检查 user.FirstName
是 Null 还是 WhiteSpace。当 user.FirstName
的值为 null 时,此代码段抛出 NullReferenceException
。我假设这是通过检查 user.FirstName
的 Length
抛出的,但由于这是短路检查,第一个表达式不应该满足条件并执行 if 块内的代码。或者我在这里遗漏了什么。
第二部分只在
时执行
string.IsNullOrWhiteSpace(user.FirstName)
结果为真。所以你需要
!string.IsNullOrWhiteSpace(user.FirstName) && !(user.FirstName.Length <= 64)
或
string.IsNullOrWhiteSpace(user.FirstName) || !(user.FirstName.Length <= 64)
取决于您的要求。此外,user
可能是 null
,在这种情况下,短路根本无济于事。
&&
并没有像你想象的那样短路,恰恰相反。
如果第一个条件为真,它需要检查两个条件,只有当两个条件都为真时,它才会执行内部块:如果第一个条件为真(即 user.FirstName
为空),则它也需要检查第二个是否为真,因此您的异常(因为 user.FirstName
在检查其 Length
时将始终为空 - 除非它为空或空白)。
编辑:由于上面这段话对某些人来说似乎不清楚:我不是说&&
不短路(它会如果第一个条件是 false
,则短路),我是说它不会像 OP
预期的那样短路
在发布不断言之前让我们分析一下你的问题
(C# 解决方案包含 十亿行代码 :您真的认为
if
这么普通的构造能行不通吗?)
您似乎想检查用户名是否无效一个:
- 如果用户名为 null 或空或白色 space
- 或者如果它太长(超过 64 个字符)
现在实现很清楚了:
const int USER_NAME_MAX_LENGTH = 64;
if (string.IsNullOrWhiteSpace(user.FirstName) ||
user.FirstName.Length > USER_NAME_MAX_LENGTH) {
// user name is invalid
...
}
在您的示例中,NullReferenceException
可能有两个不同的原因:
- Value `user` is null;
- `user.FirstName` is null.
我假设您已经检查过 user
是否不为空,所以让我们跳过那个。
现在假设 user.FirstName
为空,那么会发生什么?
第一个条件 string.IsNullOrWhiteSpace(user.FirstName)
将导致 true
。这足以让 if 语句执行内部代码块还是应该评估第二个条件?
来看看这个真相-table:
A && B = RESULT
--------------------
False False = False
False True = False
True False = False
True True = True
因此,当使用 &&
运算符时,只有当两个子条件都为真时,总条件才为真。所以当第一个条件为真时,第二个条件仍然需要评估。根据 C# 的 truth-table 的简单翻译是(其中 ??? 代表:不关心):
A && B = RESULT
--------------------
False ??? = False
True False = False
True True = True
所以当检查你的第二个条件时,属性 user.FirstName.Length
被读取,导致你的 NullReferenceException
.
如何防止这种情况。正如其他人所说,您可能希望在以下情况下执行代码块: FirstName
为 NULL OR Empty OR WhiteSpace OR 大于 64。基本上,您当前的条件检查 FirstName 是否为 NULL AND 是否大于 64.
所以...使用 ||-运算符:
if (string.IsNullOrWhiteSpace(user.FirstName) || !(user.FirstName.Length <= 64))
或更清楚:
if (string.IsNullOrWhiteSpace(user.FirstName) || (user.FirstName.Length > 64))
C# 真相-table 将是:
A || B = RESULT
--------------------
False False = False
False True = True
True ??? = True
你可以清楚地看到"short circuit"部分。
我有一个抛出 NullReferenceException 的代码段。代码段是这样的
if (string.IsNullOrWhiteSpace(user.FirstName) && !(user.FirstName.Length <= 64))
{
// Some Code
}
这里的 if 条件首先应该检查 user.FirstName
是 Null 还是 WhiteSpace。当 user.FirstName
的值为 null 时,此代码段抛出 NullReferenceException
。我假设这是通过检查 user.FirstName
的 Length
抛出的,但由于这是短路检查,第一个表达式不应该满足条件并执行 if 块内的代码。或者我在这里遗漏了什么。
第二部分只在
时执行string.IsNullOrWhiteSpace(user.FirstName)
结果为真。所以你需要
!string.IsNullOrWhiteSpace(user.FirstName) && !(user.FirstName.Length <= 64)
或
string.IsNullOrWhiteSpace(user.FirstName) || !(user.FirstName.Length <= 64)
取决于您的要求。此外,user
可能是 null
,在这种情况下,短路根本无济于事。
&&
并没有像你想象的那样短路,恰恰相反。
如果第一个条件为真,它需要检查两个条件,只有当两个条件都为真时,它才会执行内部块:如果第一个条件为真(即 user.FirstName
为空),则它也需要检查第二个是否为真,因此您的异常(因为 user.FirstName
在检查其 Length
时将始终为空 - 除非它为空或空白)。
编辑:由于上面这段话对某些人来说似乎不清楚:我不是说&&
不短路(它会如果第一个条件是 false
,则短路),我是说它不会像 OP
在发布不断言之前让我们分析一下你的问题
(C# 解决方案包含 十亿行代码 :您真的认为
if
这么普通的构造能行不通吗?)
您似乎想检查用户名是否无效一个:
- 如果用户名为 null 或空或白色 space
- 或者如果它太长(超过 64 个字符)
现在实现很清楚了:
const int USER_NAME_MAX_LENGTH = 64;
if (string.IsNullOrWhiteSpace(user.FirstName) ||
user.FirstName.Length > USER_NAME_MAX_LENGTH) {
// user name is invalid
...
}
在您的示例中,NullReferenceException
可能有两个不同的原因:
- Value `user` is null;
- `user.FirstName` is null.
我假设您已经检查过 user
是否不为空,所以让我们跳过那个。
现在假设 user.FirstName
为空,那么会发生什么?
第一个条件 string.IsNullOrWhiteSpace(user.FirstName)
将导致 true
。这足以让 if 语句执行内部代码块还是应该评估第二个条件?
来看看这个真相-table:
A && B = RESULT
--------------------
False False = False
False True = False
True False = False
True True = True
因此,当使用 &&
运算符时,只有当两个子条件都为真时,总条件才为真。所以当第一个条件为真时,第二个条件仍然需要评估。根据 C# 的 truth-table 的简单翻译是(其中 ??? 代表:不关心):
A && B = RESULT
--------------------
False ??? = False
True False = False
True True = True
所以当检查你的第二个条件时,属性 user.FirstName.Length
被读取,导致你的 NullReferenceException
.
如何防止这种情况。正如其他人所说,您可能希望在以下情况下执行代码块: FirstName
为 NULL OR Empty OR WhiteSpace OR 大于 64。基本上,您当前的条件检查 FirstName 是否为 NULL AND 是否大于 64.
所以...使用 ||-运算符:
if (string.IsNullOrWhiteSpace(user.FirstName) || !(user.FirstName.Length <= 64))
或更清楚:
if (string.IsNullOrWhiteSpace(user.FirstName) || (user.FirstName.Length > 64))
C# 真相-table 将是:
A || B = RESULT
--------------------
False False = False
False True = True
True ??? = True
你可以清楚地看到"short circuit"部分。