5

他の人が書いたコードをリファクタリングしているときに、私には理解できない奇妙なことに出くわしました。なぜそれが起こるのか誰かが説明してくれることを願っています。

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 への代入が行われていると私は考えています。私の 3 番目のコードはうまく伝わらないかもしれませんが、それを表現するより良い方法は思いつきません!

要するに:

  1. 3 番目のコード スニペットは常に最初のコード スニペットと同じ結果になりますか?
  2. 最初のコード スニペットが 2 番目のコード スニペットと同じことをしないのはなぜですか?
4

3 に答える 3

11

優先順位は操作順序付けではなく、操作を結合することです。実行順序は常に左から右です。たとえば、次のように記述します。

int a = x * (y / z);

thenxはまだ前に評価されy / zます。

したがって、この表現では:

if (mystring.Length != (mystring = mystring.Replace("!#", replacement)).Length)

我々は持っています:

  • 評価mystring.Lengthします (この値をxと呼びます)
  • 評価(mystring = mystring.Replace("!#", replacement)).Length
    • 評価mystring.Replace("!#", replacement)
    • 結果をに割り当てますmystring
    • 長さを取得します (この値をyと呼びます)
  • xyを比較する

混乱から明らかなように、このコードはひどいものです。現在の形式からリファクタリングしてくれたことを嬉しく思います。

于 2013-09-17T16:52:00.090 に答える
0

1: いいえ。最初のコード スニペットでは、mystring変数がif と else の両方で変更され、比較式が評価されます。したがって、同じ結果を得るには、3 番目のコード スニペットを次のように変更します。

string temp1 = mystring.Replace("!#", replacement);
string temp2 = **temp1**.Replace("#", replacement);
if (mystring.Length != temp1.Length)
{
    i = 1;
}
....

2: mystringがちょうど 2 回変更されるため

于 2013-09-17T17:03:45.487 に答える
0

元のコードは実際には次のようになります。

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;
}

これは、実行順序が左から右になるためです。

これにより、文字列の長さが決定され、文字列が変更され、長さがフェッチされて比較されます。

このタイプのコードは、ほとんどの場合避けるべきものであることに注意してください。ブール式内でデータを変更することは、ほとんどの場合、悪い考えであり、チェックしている同じデータを変更すると、これが非常に混乱します。

于 2013-09-17T16:51:46.940 に答える