While refactoring some code written by someone else, I've come across some weirdness that I don't understand, and I'm hoping someone can explain why it happens.
if (mystring.Length != (mystring = mystring.Replace("!#", replacement)).Length)
{
i = 1;
}
else if (mystring.Length != (mystring = mystring.Replace("#", replacement)).Length)
{
i = -1;
}
What I thought would happen here would be that as brackets have the highest precedence, the assignment inside the brackets would happen first and none of the code inside the if and else if blocks would be executed. Here is what I thought this code was effectively doing:
mystring = mystring.Replace("!#", replacement);
if (mystring.Length != mystring.Length)
{
i = 1;
}
else
{
mystring = mystring.Replace("#", replacement);
if (mystring.Length != mystring.Length)
{
i = -1;
}
}
I thought that the only thing that would happen would be the changes to mystring
, as the assignment would be made before the comparison. Testing this out has shown that what happens is actually closer to this:
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;
}
If that isn't clear, what I think is happening is that the assignment to mystring is being made after the truth of the expression is evaluated, rather than as the first part of evaluating that expression as I had thought. My third piece of code might not get that across very well but I can't think of a better way to express it!
In short:
Precedence isn't about ordering operations - it's about binding operations together. The execution order is always left to right. So for example, if you write:
int a = x * (y / z);
then x
is still evaluated before y / z
.
So in this expression:
if (mystring.Length != (mystring = mystring.Replace("!#", replacement)).Length)
we have:
mystring.Length
(we'll call this value x)(mystring = mystring.Replace("!#", replacement)).Length
mystring.Replace("!#", replacement)
mystring
As is clear from the confusion, this code is horrible - I'm glad you're refactoring it away from its current form.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With