2009-04-27 26 views
16

Rõ ràng đây từng là một cách trong VB6 và VBA để ngắn mạch và thực hiện các trường hợp thực sự đầu tiên:Select Case Đúng

Select Case True 
End Select 

Đây có phải là vẫn còn trong sử dụng (VB.NET)?

+0

Sử dụng các toán tử ngắn mạch 'AndAlso' và' OrElse' trong VB.NET, thay vì hack 'Chọn Case' này. –

Trả lời

26

Cú pháp này thường được sử dụng thay vì một If...ElseIf tuyên bố. Một số người tìm thấy nó dễ đọc hơn một chút. Ví dụ:

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 

Câu trả lời là có, điều này vẫn hoạt động trong VB.NET. Chỉ cần cẩn thận khi bạn sử dụng nó, bởi vì nó không phải là "cấu trúc lập trình chuẩn" và có thể không quen với những người phải duy trì mã của bạn trong tương lai.

+0

Vâng, đó là một. Cảm ơn! –

3

Bạn có ý nghĩa như thế này không?

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

Trong đó, chương trình sẽ viết 2 ... nếu đó là những gì bạn đang yêu cầu, sau đó có, đó vẫn là xung quanh trong VB.NET

12

Tôi không chắc chắn như thế nào cấu trúc này cung cấp bất kỳ lợi thế hơn như sau:

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 

Cấu trúc trên là chập mạch, và tôi không cần phải cố gắng làm việc ra những gì nó làm như nó là một cấu trúc tiêu chuẩn.

+0

Nó không, nhưng nhiều lập trình viên VB sai ở phía bên của định dạng hoàn toàn có thể đọc được, và nó có thể được lập luận rằng câu hỏi mô tả chính xác điều kiện đó. Càng nhiều C-esque của các nhà phát triển ra có chắc chắn trong trại của bạn mặc dù. Xem thêm @RolandTumble. – Hardryv

9

Những người khác đã trả lời câu hỏi thực tế đó, nhưng tôi chỉ muốn kêu gọi trong đó tôi sử dụng cấu trúc này khá thường xuyên. Tôi nghĩ đó là thường cách có thể đọc được hầu hết đồng thời kiểm tra hai điều kiện boolean:

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 

Tôi thừa nhận rằng một phần của lý do tại sao tôi tìm thấy nó dễ dàng có thể đọc được là tôi làm sử dụng nó, và rằng tôi nhớ lại cần phải phân tích nó các lần đầu tiên tôi nhìn thấy nó - nhưng khi phân tích cú pháp thành công, phản ứng của tôi là "Thật tuyệt vời!"

9

Có rất nhiều sự nhầm lẫn về chủ đề này, nhưng để trả lời câu hỏi OPS: Có, đánh giá hợp lý là giống nhau trong VB.Net như trong VB6 vì nó nằm trong VBA. http://support.microsoft.com/kb/817250

Để tận dụng kỹ thuật Chọn tối ưu hóa trường hợp, bạn sử dụng cú pháp cố định Chọn trường hợp để tránh sử dụng toán tử logic và, hoặc, Xor, v.v.

Hãy xem xét ví dụ sau:

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 

Các Select Case phiên bản sẽ chỉ chạy A. Nếu-Block sẽ chạy cả hai. Đây không phải là lỗi của tuyên bố, đúng hơn là lỗi của toán tử And. Nếu bạn thích, bạn có thể cấu trúc Câu lệnh if thành ngắn mạch như sau:

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

Và B sẽ không chạy. Đó chỉ là vấn đề về phong cách.

Điều quan trọng cần biết là những gì bạn đang tránh là toán tử And/Or/Xor không phải là khối If. Nếu bạn thích phiên bản Select Case của If-Block tốt hơn ... Thêm sức mạnh cho bạn :)

+3

Lưu ý rằng bạn có thể sử dụng OrElse để đoản mạch và chỉ chạy A. – Jack

3

Select Casea powerful operator by itself. Nhưng mặc dù Select Case True vẫn được hỗ trợ, tốt hơn là nên tránh cho quan điểm bảo trì.Bạn luôn phải biện minh cho nhu cầu. Nếu cần thiết, bạn thậm chí có thể sử dụng DoEventsGoTo. Đối với câu trả lời được chấp nhận, câu trả lời có thể được viết như thế này:

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 
+0

Nitpicky để chỉ ra, nhưng '0' không phải là "giá trị dương". ^^ – Hardryv

+1

@Hardryv: Bây giờ có tốt hơn không? :) – Neolisk

+0

thực sự nó là;) – Hardryv

2

Bạn có thể xác định Toán tử bằng bất kỳ loại trình bao bọc nào. Sau đó, bạn có thể sử dụng loại Trình bao bọc trên Trường hợp Chọn.

Trình bao bọc mẫu.

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 

Bây giờ bạn có thể sử dụng _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 

Về Performance. Mã phát hành được tối ưu hóa. Wrapper không bị phạt.

+0

đẹp nhất x77. ^^ – Hardryv

1

Sau khi đọc chủ đề này, có vẻ như đối số chính cho Select Case True là khả năng đọc. Như thế này đủ chưa? Khi tôi lần đầu tiên nhìn thấy các cấu trúc được sử dụng như thế này trong VB.NET, tôi đã phải đọc qua nó một vài lần để chắc chắn rằng tôi đã có ý chính của nó, nhưng vẫn nghĩ dọc theo các dòng tương tự như RolandTumble, above. Vì vậy, ngay cả khả năng đọc được đi kèm với một chi phí nhỏ. Mọi người đều biết lời tuyên bố của If...ElseIf...End If là gì và tại sao nó ở đó. Ngắn mạch có thể được hỗ trợ bằng cách sử dụng AndAlso hoặc OrElse, và phức tạp là hoàn toàn xuống đến mã và coder tham gia.

Thậm chí có thể tối ưu hóa các tuyên bố If. Điểm trong việc hỏi rõ ràng (cho dù là value = True) của bạn. Tôi đã từng hỏi sau đây đã làm bởi một coder làm việc với chúng tôi ...

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

Việc sử dụng các cấu trúc Select Case True cũng cảm thấy như bạn đang di chuyển trọng tâm hay sự nhấn mạnh so ra khỏi Select Case dòng thực tế và vào các câu lệnh Case, lẻ như điều đó có thể phát ra âm thanh.

1

Một lý do khác cho việc sử dụng cấu trúc SELECT CASE TRUE là khi báo cáo trường hợp của bạn đánh giá thành giá trị boolean. TRƯỜNG HỢP CHỌN cần phải có tất cả các trường hợp đánh giá cùng một kiểu dữ liệu như kiểm soát. Nếu bạn đang xem xét một kiểu dữ liệu chuỗi, thì tất cả các câu lệnh case cũng cần phải là chuỗi.

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

Tuy nhiên nếu bạn so sánh các chuỗi một phần bằng toán tử LIKE thì kiểu dữ liệu trường hợp của bạn sẽ không khớp với điều khiển chuỗi. Đoạn mã dưới đây sẽ không làm việc:

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

Để sử dụng ký tự đại diện (và do đó có kết quả trường hợp boolean), bạn cần phải có một giá trị kiểm soát boolean, do đó cấu trúc cần phải được:

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

Tôi cho rằng bạn có thể sử dụng IF ... ELSEIF

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

Cá nhân tôi thấy trường hợp SELECT dễ sử dụng hơn và đọc khi có nhiều hơn ba tùy chọn. Tôi sử dụng IF ... ELSE và IF ... ELSEIF khi tôi phải đánh giá hai hoặc ba tùy chọn khác nhau (>, =, <) hoặc nếu tôi đang thử nghiệm một giá trị cho một phạm vi cụ thể của các mục 'hợp lệ'. Nếu thay vào đó mục nhập có nhiều hơn và tôi cần xác định mười khả năng nào đã xảy ra, CASE SELECT là một cấu trúc dễ sử dụng hơn nhiều vì nó loại bỏ sự cần thiết cho nhiều câu lệnh OR.

Các vấn đề liên quan