计算 if 语句中的表达式
本文关键字:表达式 语句 if 计算 | 更新日期: 2023-09-27 18:31:51
在重构别人写的一些代码时,我遇到了一些我不理解的奇怪之处,我希望有人能解释为什么会发生这种情况。
if (mystring.Length != (mystring = mystring.Replace("!#", replacement)).Length)
{
i = 1;
}
else if (mystring.Length != (mystring = mystring.Replace("#", replacement)).Length)
{
i = -1;
}
我认为这里会发生的情况是,由于括号具有最高的优先级,括号内的赋值将首先发生,而if和else if块中的任何代码都不会被执行。以下是我认为这段代码有效地执行的操作:
mystring = mystring.Replace("!#", replacement);
if (mystring.Length != mystring.Length)
{
i = 1;
}
else
{
mystring = mystring.Replace("#", replacement);
if (mystring.Length != mystring.Length)
{
i = -1;
}
}
我认为唯一会发生的事情是对mystring
的更改,因为分配将在比较之前进行。测试表明,发生的事情实际上更接近于此:
string temp1 = mystring.Replace("!#", replacement);
string temp2 = mystring.Replace("#", replacement);
if (mystring.Length != temp1.Length)
{
i = 1;
}
else if (mystring.Length != temp2.Length)
{
i = -1;
}
if (i == 1)
{
mystring = temp1;
}
else
{
mystring = temp2;
}
如果这还不清楚,我认为正在发生的事情是,对mystring的赋值是在评估表达式的真实性之后进行的,而不是像我想象的那样作为评估该表达式的第一部分。我的第三段代码可能无法很好地表达它,但我想不出更好的表达方式!
总之:
- 我的第三个代码片段是否总是给出与第一个相同的结果?
- 为什么第一个代码片段不与第二个代码片段执行相同的操作?
优先级不是关于对操作进行排序 - 而是关于将操作绑定在一起。执行顺序始终从左到右。例如,如果您编写:
int a = x * (y / z);
那么x
在y / z
之前仍然被评估。
所以在这个表达中:
if (mystring.Length != (mystring = mystring.Replace("!#", replacement)).Length)
我们有:
- 评估
mystring.Length
(我们将此值称为 x) - 评估
(mystring = mystring.Replace("!#", replacement)).Length
- 评估
mystring.Replace("!#", replacement)
- 将结果分配给
mystring
- 取长度(我们称此值为 y)
- 评估
- 比较 x 和 y
从混乱中可以清楚地看出,这段代码很糟糕 - 我很高兴你正在重构它,使其脱离当前的形式。
原文中的代码实际上更接近:
int length1 = mystring.Length;
mystring = mystring.Replace("!#", replacement); // First nested paren on RHS
int length2 = mystring.Length; // second "length" check on RHS
if (length1 != length2)
{
i = 1;
}
这是因为执行顺序将从左到右。
这会导致确定字符串的长度,然后字符串发生突变,然后获取并比较长度。
请注意,这种类型的代码几乎总是应该避免的。 在布尔表达式中改变数据几乎总是一个坏主意,并且改变您正在检查的相同数据会使这非常混乱。
1:否。在您的第一个代码片段中,mystring 变量在 if 和 else 中都会更改以评估比较表达式。因此,要获得相同的结果,请将第三个代码片段更改为:
string temp1 = mystring.Replace("!#", replacement);
string temp2 = **temp1**.Replace("#", replacement);
if (mystring.Length != temp1.Length)
{
i = 1;
}
....
2:因为mystring正好更改了两次