【发布时间】:2009-04-27 15:26:53
【问题描述】:
显然这曾经是VB6和VBA中短路并执行第一个真实案例的一种方式:
Select Case True
End Select
这还在使用吗(VB.NET)?
【问题讨论】:
-
在 VB.NET 中使用
AndAlso和OrElse短路运算符,而不是Select Casehack。
显然这曾经是VB6和VBA中短路并执行第一个真实案例的一种方式:
Select Case True
End Select
这还在使用吗(VB.NET)?
【问题讨论】:
AndAlso 和 OrElse 短路运算符,而不是 Select Case hack。
此语法通常用于代替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 中仍然有效。使用时请注意,因为它不是“标准编程结构”,将来必须维护您的代码的人可能不熟悉。
【讨论】:
if (a) {Do A} else { if (b) {Do B} else { if (c) {Do C} } } } 等的 if else 问题。这也意味着你的测试用例写在一个整洁的列表中(人眼擅长),而不是而不是嵌套在一个页面中。
我不确定这个构造如何比以下内容提供任何优势:
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
上面的结构是短路的,因为它是一个标准结构,所以我不必尝试弄清楚它的作用。
【讨论】:
其他人已经回答了这个实际问题,但我只想说我经常使用这个结构。我认为这通常是同时测试两个布尔条件的最易读的方法:
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
我承认我觉得它易于阅读的部分原因是我确实使用了它,而且我记得我第一次看到它时不得不解析它——但一旦成功解析,我的反应是“太棒了! "
【讨论】:
关于这个主题有很多困惑,但要回答 OP 的问题:是的,VB.Net 中的逻辑评估与 VB6 中的逻辑评估和 VBA 中的逻辑评估相同。 http://support.microsoft.com/kb/817250
要利用 Select Case 优化技术,您可以使用 Select Cases 固有语法来避免使用逻辑运算符 And、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 块。如果您更喜欢 If-Block 的 Select Case 版本...为您提供更多功能:)
【讨论】:
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
【讨论】:
你的意思是这样的吗?
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 中仍然存在
【讨论】:
您可以在任何包装器类型上定义等于运算符。 然后你可以在 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 没有性能损失。
【讨论】:
使用构造 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
p>本地,当有三个选项时,我发现选择案例更易于使用和读取。当我必须评估两个或三个不同的选项(>、=、
【讨论】:
阅读此线程后,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 语句中,这听起来很奇怪。
【讨论】: