1

私は$COMPANYで働いており、$LEGACY_APPLICATIONの維持を支援しています。VisualBasic6で書かれています。

ifステートメントで短絡評価を実行するVB6の機能がないため、不快に複雑なネストされたifステートメントを実行することに直面しました(これにより、これが大幅に簡素化されます)。AndAlsoを試しましたが、役に立ちませんでした。VB6の後に追加された機能である必要があります。

SOのある天才は、忍耐力があれば、select caseステートメントをだまして短絡ifステートメントのように機能させることができると指摘したので、それを試しました。これが私が思いついたものです。

Select Case (True) ' pretend this is an if-else statement
    Case (item Is Nothing): Exit Sub ' we got a non-element
    Case ((item Is Not Nothing) And (lastSelected Is Nothing)): Set lastSelected = item ' we got our first good element
    Case (item = lastSelected): Exit Sub ' we already had what we got
    Case (Not item = lastSelected): Set lastSelected = item ' we got something new
End Select

それは間違いなく少し珍しいことであり、すべてのステートメントを正しくマッピングしたことを確認するために、私の素晴らしいホワイトボード(ちなみに、コンピューター以外で最も便利なプログラミングリソースです)を利用する必要がありました。

そこで起こっていることは次のとおりです。私には高価な操作があり、可能であれば繰り返さないようにしたいと思います。lastSelectedは、この計算に最後に渡された値への永続的な参照です。itemは、GUIから受け取ったばかりのパラメーターです。これまでにプログラムへの呼び出しがなかった場合、lastSelectedはNothingとして開始されます。アイテムも何もできません。さらに、lastSelectedとitemの両方が同じものである場合は、計算をスキップします。

これをC++で書いているとしたら、次のように書きます。

if (item == NULL || (lastSelected != NULL && item->operator==(*lastSelected))) return;
else lastSelected = item;

しかし、私はそうではありません。

質問

どうすればこれを書き直して見栄えを良くし、より意味のあるものにすることができますか?賛成票は、「はい、理由はX、Y、Z」または「いいえ、理由はX、Y、Z」のいずれかであると回答した場合に授与されます。

編集

C ++ステートメントをVB6ステートメントと一致するように修正しました(同等であると想定されていました)

4

4 に答える 4

4

これは短く、100倍読みやすくなっています。

編集Wugは、MarkJの元の回答のコードを次のように編集しました。

If (item Is Nothing)
    Then Exit Sub ' we got a non-element
ElseIf (lastSelected Is Nothing) Then
    Set lastSelected = item ' we got our first go 
ElseIf (item = lastSelected) Then
    Exit Sub ' we already had what we got
End If
Set lastSelected = item ' we got something new 

これがMarkJのそれに応じた編集です。1つはネストされていますが、1つのセットのみです。私にはすっきりしているようだ。

If (item Is Nothing) Then 
  Exit Sub ' we got a non-element 
ElseIf Not (lastSelected Is Nothing) Then ' not our first go
  If (item = lastSelected) Then 
    Exit Sub ' we already had what we got 
  End If 
End If
Set lastSelected = item ' we got something new
' does stuff here? @Wug is that true?
  • VB6で参照の同等性を比較するには、項目IsLastSelectedを使用します。item = lastSelectedはおそらくオブジェクトのデフォルトのプロパティを評価し、代わりにそれらを比較するためです。
  • 簡潔さが目標のように見えるので、これを考慮してください。条件XがTrueのときにSubを終了すると、後でXを再度チェックする必要はありません。それは誤りです!評価の合間に値を変更しない限り(たとえば、Xはシステムクロックをチェックする関数です)。アイテムがlastSelectedであるかどうか、次にそうでないかどうかを確認していました。また、アイテムが偽物ではない場合は、アイテムが偽物ではないかどうかをわざわざ確認しないでください。
  • VB6は、Basicの古いバージョンとの下位互換性のために短絡しません
  • VB6が他の言語ではないことを心配するのをやめて、リラックスしてください。
于 2012-07-20T05:50:16.413 に答える
3

はい

私はあなたのcaseステートメントからそれを翻訳しました。個人的には読みやすいと思います。

If Item Is Nothing Then
  Exit Sub ' we got a non-element
ElseIf LastSelected Is Nothing Then
  Set LastSelected = Item ' we got our first good element
ElseIf Item = LastSelectedItem Then
  Exit Sub ' we already had what we got
Else
  Set LastSelected = Item ' we got something new
End If

あなたは説明を求めました。私は(あなた自身のコードコメントを再利用することによって)多くを与える必要がないように努めました。

しかし、ここにとにかくあります:-)

  • まず、アイテムがない場合は、終了します。簡単。
  • それ以外の場合は、最初のif条件が失敗したため、それが存在し、その値を最後に選択されたものとしてマークするのが安全でLastSelected Is Nothingあることがわかります。Itemあなたが言うように、私たちは最初の良い要素を手に入れました。潜水艦は続きます。
  • Itemただし、との既存の値がLastSelectedある場合、それらは等しいかどうかのどちらかです。それらが等しい場合は、終了します。
  • それらが等しくない場合は、を更新しLastSelectedます。あなたが言うように、私たちは何か新しいものを手に入れました
于 2012-07-20T01:18:23.637 に答える
1

次のようなヘルパー関数を使用できます。

Private Function pvGetItemData(oItem As ListItem) As Variant
    If Not oItem Is Nothing Then
        pvGetItemData = oItem.Tag
    Else
        pvGetItemData = -1
    End If
End Function

その後

If pvGetItemData(Item) = pvGetItemData(LastSelected) Then
    ' cache hit
Else
    ' do calc
    Set LastSelected = Item
End If
于 2012-07-20T11:44:39.563 に答える
0

はい

私はそれをもっと簡単にします:

If item Is Nothing Then
  Exit Sub ' we got a non-element
Else
  Set lastSelected = item ' we got something to assign
End If

lastItemを割り当てる副作用がない限り(無効な割り当てコードを持つプロパティである可能性があります)、コードロジックは基本的に同じです。

subを終了する必要がない場合(スニペットはsubなどの最後にあります)、nextはさらに簡単です。

If Not (item Is Nothing) Then Set lastSelected = item

ところで、あなたSelect Case (True)はVBプログラマーには本当に奇妙に見えます:)

于 2012-07-20T06:20:00.560 に答える