2009-04-27 13 views
16

Najwyraźniej kiedyś sposobem w VB6 i VBA do zwarcia i wykonać pierwszy prawdziwy przypadek:Select Case prawda

Select Case True 
End Select 

Czy to nadal w użyciu (VB.NET)?

+0

Należy używać operatorów zwartych 'AndAlso' i' OrElse' w VB.NET zamiast tego hackowania "Wybierz Case". –

Odpowiedz

26

składnia ta jest często stosowany zamiast If...ElseIf komunikat. Niektórzy uważają, że czytanie jest trochę łatwiejsze. Na przykład:

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 

Odpowiedź brzmi: tak, to nadal działa w VB.NET. Dbaj tylko o to, kiedy go używasz, ponieważ nie jest to "standardowa konstrukcja programistyczna" i może być nieznana dla osób, które będą musiały utrzymać Twój kod w przyszłości.

+0

Tak, to jedyny. Dzięki! –

3

Masz na myśli coś takiego?

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

W którym program będzie napisać 2 ... jeśli o to pytasz, to tak, że jest wciąż wokół w VB.NET

12

Nie jestem pewien, jak to konstrukt oferuje żadnych korzyści nad następującym:

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 

Powyższa struktura jest zwarcie, a nie starać się wypracować to, co robi, jak to standardowa konstrukcja.

+0

Nie robi tego, ale wielu programistów VB popełnia błąd po stronie najbardziej czysto czytelnego formatu i można argumentować, że pytanie dokładnie opisuje ten warunek. Im więcej twórców C-esque jest zdecydowanie w twoim obozie. Zobacz także @RolandTumble. – Hardryv

9

Inni już odpowiedzieli na to pytanie, ale chcę tylko powiedzieć, że używam tego konstruktu dość często. Myślę, że to często najbardziej czytelny sposób jednoczesnego testowania dwóch logicznych warunki:

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 

muszę przyznać, że część dlaczego uważam, że łatwo czytelne jest to, że robię z niego skorzystać, i że ja pamiętam konieczności go do analizowania Po raz pierwszy zobaczyłem to - ale po pomyślnym przetworzeniu, moja reakcja była "To genialne!"

9

Istnieje wiele zamieszania na ten temat, ale aby odpowiedzieć na pytanie OP: Tak, ocena logiczna jest taka sama w VB.Net, jak to jest w VB6, jak to jest w VBA. http://support.microsoft.com/kb/817250

Aby skorzystać z techniki optymalizacji Select Case, należy użyć składni właściwej, aby uniknąć użycia operatorów logicznych, Or, Xor itd. To właśnie operatorzy mają ocenę Short-Circuit.

Rozważmy następujący przykład:

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 

Wersja Select Case będzie działać tylko A. Jeśli-Block będzie działał zarówno. To nie jest, jeśli instrukcja jest błędem, a raczej jest winą operatora I. Jeśli wolisz, możesz skonstruować instrukcję If na zwarcie tak:

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

A B nie będzie działać. To wszystko tylko kwestia stylu.

Najważniejszą rzeczą jest to, że unika się operatorów I/Or/Xor, a nie bloków If. Jeśli podoba Ci się wersja Select Case-Block lepiej ... Więcej mocy dla ciebie :)

+3

Zauważ, że możesz użyć OrElse do zwarcia i uruchomić tylko A. – Jack

3

Select Case to a powerful operator by itself. Ale nawet jeśli Select Case True jest nadal obsługiwany, lepiej jest go unikać ze względu na łatwość konserwacji.Zawsze musisz uzasadnić potrzebę. W razie potrzeby można nawet użyć DoEvents i GoTo. W przypadku zaakceptowanej odpowiedzi można było napisać w ten sposób:

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, aby wskazać, ale "0" nie jest "wartością dodatnią". ^^ – Hardryv

+1

@Hardryv: Czy teraz jest lepiej? :) – Neolisk

+0

istotnie jest;) – Hardryv

2

Można zdefiniować operatora równego na dowolnym typie opakowania. Następnie można użyć typu Wrapper w Select Case.

Opakowanie próbek.

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 

Teraz można użyć _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 

o wydajność. Kod wersji jest zoptymalizowany. Wrapper nie ma kary za wydajność.

+0

fajny x77. ^^ – Hardryv

1

Po przeczytaniu tego wątku wygląda na to, że głównym argumentem dla Select Case True jest czytelność. Czy to wystarczy? Kiedy po raz pierwszy zobaczyłem konstrukcję używaną w VB.NET, musiałem przeczytać ją kilka razy, aby upewnić się, że rozumiem, ale wciąż myślę tak samo jak RolandTumble, above. Więc nawet czytelność przynosi niewielki koszt. Wszyscy wiedzą, co to jest oświadczenie i dlaczego tak jest. Zwarcie może być wspomagane przy użyciu AndAlso lub OrElse, a złożoność zależy wyłącznie od kodu i kodera.

Nawet instrukcje If można zoptymalizować. Po co pytać oczywiste (czy to twoje value = True). Kiedyś zapytałem co następuje zrobił przez koder pracujących z nami ...

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

Zastosowanie struktury Select Case True czuje się również jak ruszasz ostrości lub porównywania nacisk od rzeczywistej Select Case linii i w stwierdzeniach Case, co może wydawać się dziwne.

1

Innym powodem użycia konstruktu SELECT CASE TRUE jest sytuacja, w której instrukcje case mają wartość boolowską. SELECT CASE wymaga, aby wszystkie przypadki były oceniane na ten sam typ danych, co kontrolka. Jeśli patrzysz na typ danych łańcuchowych, wszystkie instrukcje case również muszą być ciągami.

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

Jednak jeśli porównujesz częściowych ciągów za pomocą operatora LIKE następnie typ danych przypadek staje się logiczna, która nie będzie pasował do kontroli ciągu. Poniższy kod nie zadziała:

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

Aby korzystać z symboli wieloznacznych (a więc mają logicznych przypadków rezultaty) trzeba mieć wartość logiczną sterowania, dzięki czemu struktura musi być:

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

Przypuszczam, że można użyć, jeśli ... elseif

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

Osobiście uważam SELECT CASE jest łatwiejszy w użyciu i czytać, gdy istnieje więcej niż trzy opcje. Używam IF ... ELSE i IF ... ELSEIF, kiedy muszę ocenić dwie lub trzy różne opcje (>, =, <) lub jeśli testuję wartość dla określonego zakresu "prawidłowych" wpisów. Jeśli zamiast tego wpis ma większą różnorodność i muszę określić, która z dziesięciu możliwości się wydarzyła, SELECT CASE jest o wiele łatwiejszym konstruktorem do użycia, ponieważ eliminuje potrzebę wielu instrukcji OR.