显然,这曾经是VB6和VBA短路并执行第一个真实案例的一种方式:
Select Case True
End Select
这仍然在使用(VB.NET)吗?
答案 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 Case
是a powerful operator by itself。但即使仍然支持Select Case True
,最好从可维护性的角度来避免。你总是需要证明这种需要。如果需要严重,您甚至可以使用DoEvents
和GoTo
。对于接受的答案,它可能是这样写的:
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
陈述是什么以及它为什么存在。可以使用AndAlso
或OrElse
来辅助短路,复杂性完全取决于所涉及的代码和编码器。
甚至可以优化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语句的需要。