选择Case True

时间:2009-04-27 15:26:54

标签: vb.net vba vb6

显然,这曾经是VB6和VBA短路并执行第一个真实案例的一种方式:

Select Case True
End Select

这仍然在使用(VB.NET)吗?

9 个答案:

答案 0 :(得分:28)

通常使用此语法而不是If...ElseIf语句。有些人发现它更容易阅读。例如:

Select Case True
    Case testVariable < 0
         Console.Write("You must supply a positive value.")
    Case testVariable > 10
         Console.Write("Please enter a number from 0-10.")
    Case True
         Call DoWork(testVariable)
End Select

答案是肯定的,这仍然适用于VB.NET。在使用它时要小心,因为它不是“标准编程结构”,对于那些必须在将来维护代码的人来说可能并不熟悉。

答案 1 :(得分:13)

我不确定这种结构如何提供以下优势:

If testVariable < 0 Then
     Console.Write("You must supply a positive value.")
ElseIf testVariable > 10 Then
     Console.Write("Please enter a number less than 10.")
Else
     Call DoWork(testVariable)
End If

上述结构是短路的,我不必尝试弄清楚它的作用,因为它是标准结构。

答案 2 :(得分:11)

其他人已经回答了这个实际问题,但我只是想说明我经常使用这个结构。我认为这通常是同时测试两个布尔条件的最可读方式:

Dim A As Boolean
Dim B As Boolean
'
'do stuff to set values of A and B
'
Select Case True
  Case A And B
    'something
  Case A And Not B
    'something else
  Case Not A And B
    'you get the picture
  Case Else
    '...
End Select

我承认,为什么我发现它易于阅读的一部分原因是我确实使用它,并且我确实记得在我第一次看到它时必须解析它 - 但是一旦成功解析,我的反应是“那太棒了! “

答案 3 :(得分:9)

关于这个主题存在很多困惑,但回答OP问题:是的,VB.Net中的逻辑评估与VB6中的逻辑评估相同,就像在VBA中一样。 http://support.microsoft.com/kb/817250

要利用Select Case优化技术,您可以使用Select Cases固有语法来避免使用逻辑运算符和Or,Xor等。这些运算符确实具有短路评估功能。

考虑这个例子:

Public Sub Example()
    If A Or B Then
        Beep
    End If
    Select Case True
        Case A, B
            Beep
    End Select
End Sub

Private Function A() As Boolean
Debug.Print "A Ran"
    A = True
End Function

Private Function B() As Boolean
Debug.Print "B Ran"
    B = False
End Function

Select Case版本仅运行A. If-Block将同时运行。这不是If语句的错,而是And运算符的错误。如果您愿意,可以将If语句结构化为短路:

Public Sub Example2()
    If A Then
    ElseIf B Then
        Beep
    End If
End Sub

B不会跑。这只是一种风格问题。

重要的是要知道你要避免的是And / Or / Xor运算符而不是If-Blocks。如果您更喜欢If-Block的Select Case版本...更多功能给您:)

答案 4 :(得分:3)

你的意思是这样吗?

 Select Case True
    Case 1 = 0
        Console.Write("1")
    Case 1 = 1
        Console.Write("2")
    Case 2 = 2
        Console.Write("3")
End Select

其中,程序会写2 ...如果这就是你要问的,那么是的,这仍然是在VB.NET中

答案 5 :(得分:3)

Select Casea powerful operator by itself。但即使仍然支持Select Case True,最好从可维护性的角度来避免。你总是需要证明这种需要。如果需要严重,您甚至可以使用DoEventsGoTo。对于接受的答案,它可能是这样写的:

Select Case testVariable
  Case Is < 0 : Console.Write("You must supply a non-negative value.")
  Case Is > 10 : Console.Write("Please enter a number from 0-10.")
  Case Else : Call DoWork(testVariable)
End Select

答案 6 :(得分:2)

您可以在任何包装类型上定义等于运算符。 然后你可以在Select Case上使用Wrapper类型。

示例包装。

Imports System.Runtime.InteropServices
<DebuggerStepThrough()> Friend Module Util
  Public Function _Is(v As Object) As IsWrapper
      Return New IsWrapper With {.Obj = v}
  End Function
  Public Structure IsWrapper
     Public Obj As Object
     Public Shared Operator =(ByVal a As IsWrapper, ByVal b As Object) As Boolean
         Return a.Obj Is b
     End Operator
     Public Shared Operator <>(ByVal a As IsWrapper, ByVal b As Object) As Boolean
         Return a.Obj IsNot b
     End Operator
  End Structure
End Module

现在你可以使用_is(AnyObject):

Private Sub RbClass_CheckedChanged(sender As System.Object, e As System.EventArgs)
    If DirectCast(sender, RadioButton).Checked = False Then Return
    Select Case _Is(sender)
        Case RbClass : Rb = 0
        Case RbTablePredicate : Rb = 1
        Case RbTableRowFilter : Rb = 2
    End Select
    QueryCtl1_QueryChanged(Nothing, Nothing)
End Sub

Public Sub Predicate(ByVal PredicateType As Type, ByVal Op As Operadores, ByVal Obj As Object, ByVal CompareOptions As CompareOptions, ByVal Fnc As [Delegate])
   Dim pred As [Delegate] = Nothing
   Select Case _Is(PredicateType)
      Case GetType(Boolean)
          pred = New Predicate(Of Boolean)(Function(v) v)
      Case GetType(String)
          pred = StrPredicate(Op, Obj, CompareOptions)
      Case Else 'Utilizar Generics
          pred = GenericHelper.Builder(PredicateType).Predicate(Op, Obj)
   End Select
   Predicate(pred, Fnc)
End Sub

关于效果。发布代码已经过优化。 Wrapper没有性能损失。

答案 7 :(得分:1)

阅读此主题后,似乎Select Case True的主要参数是可读性。这够了吗?当我第一次在VB.NET中看到这样使用的构造时,我不得不阅读它几次,以确保我得到它的要点,但仍然像RolandTumble, above一样思考。因此,即使可读性也需要很少的成本。每个人都知道If...ElseIf...End If陈述是什么以及它为什么存在。可以使用AndAlsoOrElse来辅助短路,复杂性完全取决于所涉及的代码和编码器。

甚至可以优化If语句。询问明显的问题是什么意思(是否value = True)。曾经有人问我和我们一起工作的编码员做了以下事情......

Dim isVisible As Boolean
....
If isVisible Then
    ....
End If

使用Select Case True结构也感觉就像是将焦点或比较重点从实际Select Case行转移到Case语句中,就像那样奇怪可能听起来。

答案 8 :(得分:1)

使用构造SELECT CASE TRUE的另一个原因是当case语句求值为布尔值时。 SELECT CASE需要将所有案例评估为与控件相同的数据类型。如果您正在查看字符串数据类型,那么所有case语句也需要是字符串。

SELECT CASE [string]
CASE "String 1", "String 2"
    [do a thing]
CASE "String 3"
    [do another thing]
END SELECT

但是,如果使用LIKE运算符比较部分字符串,那么您的案例数据类型将变为布尔值,这与字符串控件不匹配。以下代码无效:

SELECT CASE [string]
CASE LIKE "*1", "*2"
    [do a thing]
CASE LIKE "*3"
    [do another thing]
END SELECT

为了使用通配符(因此具有布尔结果),你必须有一个布尔控制值,因此结构必须是:

SELECT CASE TRUE
CASE [string] LIKE "*1", "*2"
    [do a thing]
CASE [string] LIKE "*3"
    [do another thing]
END SELECT

我想你可以使用IF ... ELSEIF

IF [string] LIKE "*1" AND [string] LIKE "*2" THEN
    [do a thing]
ELSEIF [string] LIKE "*3"
    [do another thing]
END IF

我个人认为当有三个以上选项时,SELECT CASE更易于使用和阅读。当我必须评估两个或三个不同的选项(&gt;,=,&lt;)或者我正在测试特定范围的有效&#的值时,我使用IF ... ELSE和IF ... ELSEIF 39;条目。相反,如果条目有更多变化,我需要确定发生了十种可能性中的哪一种,SELECT CASE是一个更容易使用的构造,因为它消除了对多个OR语句的需要。