1

我在 $COMPANY 工作,我正在帮助维护 $LEGACY_APPLICATION。它是用visual basic 6编写的。

由于缺乏 VB6 在 if 语句中执行短路评估的能力(这将大大简化这一点),我面临着做一个令人不快的复杂嵌套 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 开始。item 也可以是 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 的回应。一个嵌套 if,但只有一个 Set。对我来说似乎更整洁。

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 中的引用相等性,请使用项目 Is LastSelected。因为 item = lastSelected 可能会评估对象中的默认属性并进行比较!
  • 由于简洁似乎是一个目标,请考虑这一点。如果在条件 X 为 True 时退出 Sub,则以后无需再次检查 X。这是错误的!除非它在两次评估之间改变它的值(例如 X 是一个检查系统时钟的函数)。您正在检查项目是否是 lastSelected,然后是否不是。如果 item Is Nothing 为 False,请不要费心检查 item Is Not Nothing 是否为 True!
  • VB6 不会短路以向后兼容 Basic 的旧版本
  • 不用担心 VB6 不是其他语言,放松一下!
于 2012-07-20T05:50:16.413 回答
3

是的

我从你的案例陈述中翻译了它。我个人觉得更容易阅读。

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

你要求解释。我试图不必付出太多(通过重用你自己的代码注释)。

但无论如何它都在这里:-)

  • 首先,如果没有项目,只需退出。简单的。
  • 否则,如果LastSelected Is Nothing我们知道,因为第一个 if 条件失败,它Item存在,并且可以安全地将该值标记为 Last Selected。正如你所说,我们得到了第一个好的元素。潜艇继续前进。
  • 但是,如果我们有 和 的现有值ItemLastSelected那么它们要么相等,要么不相等。如果他们是平等的,那就放弃吧。
  • 如果它们不相等,则更新LastSelected. 正如你所说,我们得到了一些新的东西。
于 2012-07-20T01:18:23.637 回答
1

You can use a helper function like this:

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

and then

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 有副作用(它可以是具有无效分配代码的属性),否则代码逻辑基本相同。

如果您不需要退出子程序(代码段在子程序的末尾或其他地方),那么下一步就更简单了:

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

顺便说一句,你Select Case (True)的 VB 程序员看起来真的很奇怪 :)

于 2012-07-20T06:20:00.560 回答