Ukryte funkcje VB.NET?


121

Sporo się nauczyłem przeglądając ukryte funkcje języka C # i byłem zaskoczony, gdy nie mogłem znaleźć czegoś podobnego dla VB.NET.

Jakie są więc niektóre z jego ukrytych lub mniej znanych funkcji?

Odpowiedzi:


128

Exception WhenKlauzula jest w dużej mierze nieznane.

Rozważ to:

Public Sub Login(host as string, user as String, password as string, _
                            Optional bRetry as Boolean = False)
Try
   ssh.Connect(host, user, password)
Catch ex as TimeoutException When Not bRetry
   ''//Try again, but only once.
   Login(host, user, password, True)
Catch ex as TimeoutException
   ''//Log exception
End Try
End Sub

9
przydatne, jeśli chcesz złapać określony SQLException, powiedz -2, który, jeśli dobrze pamiętam, oznacza przekroczenie limitu czasu sieci: Catch ex as sqlException gdzie ex.code = -2
Pondidum

Łał! Po prostu przeczytałem to i natychmiast użyłem go, aby uprościć blok try / catch, który właśnie napisałem w zeszłym tygodniu. Nigdy nie było to nowe.
John M Gant

1
+1 A oto, gdzie blog zespołu NET CLR wyjaśnia, dlaczego filtry wyjątków są przydatne blogs.msdn.com/clrteam/archive/2009/02/05/ ...
MarkJ

5
Nie tylko jest to ukryte, ale również nie jest dostępne w C #.
Cheeso

82

Niestandardowe Enums

Jedną z prawdziwych ukrytych funkcji VB jest completionlistznacznik dokumentacji XML, którego można użyć do tworzenia własnych Enumtypów o rozszerzonej funkcjonalności. Ta funkcja nie działa jednak w języku C #.

Jeden przykład z mojego niedawnego kodu:

'
''' <completionlist cref="RuleTemplates"/>
Public Class Rule
    Private ReadOnly m_Expression As String
    Private ReadOnly m_Options As RegexOptions

    Public Sub New(ByVal expression As String)
        Me.New(expression, RegexOptions.None)
    End Sub

    Public Sub New(ByVal expression As String, ByVal options As RegexOptions)
        m_Expression = expression
        m_options = options
    End Sub

    Public ReadOnly Property Expression() As String
        Get
            Return m_Expression
        End Get
    End Property

    Public ReadOnly Property Options() As RegexOptions
        Get
            Return m_Options
        End Get
    End Property
End Class

Public NotInheritable Class RuleTemplates
    Public Shared ReadOnly Whitespace As New Rule("\s+")
    Public Shared ReadOnly Identifier As New Rule("\w+")
    Public Shared ReadOnly [String] As New Rule("""([^""]|"""")*""")
End Class

Teraz podczas przypisywania wartości do zmiennej zadeklarowanej jako Ruleśrodowisko IDE oferuje listę IntelliSense z możliwymi wartościami z RuleTemplates.

/EDYTOWAĆ:

Ponieważ jest to funkcja, która opiera się na IDE, trudno jest pokazać, jak to wygląda, gdy jej używasz, ale użyję tylko zrzutu ekranu:

Lista ukończenia w akcji http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png

W rzeczywistości IntelliSense jest w 100% identyczny z tym, co otrzymujesz podczas korzystania z Enum.


Ciekawe - czy możesz pokazać przykład, jak to wygląda, gdy je spożywasz?
Brian MacKay,

Wygląda na to, że ktoś mógłby nadal utworzyć własną regułę, wywołując bezpośrednio konstruktora reguł? Jeśli tak i chciałbyś to zatrzymać, czy możesz zadeklarować konstruktor jako „Przyjaciel” w swojej bibliotece?
Joel Coehoorn

Joel, w moim przykładowym kodzie intencjonalnie tego nie zabraniałem. Raczej oferuję użytkownikowi kilka wspólnych reguł i pozwalam na tworzenie własnych, specjalistycznych reguł. Możesz oczywiście temu zapobiec, oznaczając konstruktor jako friendlub używając tej samej klasy co enum: Rulezamiast RuleTemplate.
Konrad Rudolph

czy jest gdzieś lista ukrytych przydatnych zastosowań atrybutów? ten na pierwszy rzut oka wydaje się niewiarygodny, ale nie jestem jeszcze pewien, gdzie bym go użył lub czy mógłby rozwiązać podstawowy problem w niektórych przypadkach, nie mając możliwości ograniczenia rodzaju ogólnego do wyliczeń.
Maslow

@Maslow: nie ma tu żadnego atrybutu. To jest komentarz XML.
Joel Coehoorn

49

Czy zauważyłeś operator porównania Like?

Dim b As Boolean = "file.txt" Like "*.txt"

Więcej z MSDN

Dim testCheck As Boolean

' The following statement returns True (does "F" satisfy "F"?)'
testCheck = "F" Like "F"

' The following statement returns False for Option Compare Binary'
'    and True for Option Compare Text (does "F" satisfy "f"?)'
testCheck = "F" Like "f"

' The following statement returns False (does "F" satisfy "FFF"?)'
testCheck = "F" Like "FFF"

' The following statement returns True (does "aBBBa" have an "a" at the'
'    beginning, an "a" at the end, and any number of characters in '
'    between?)'
testCheck = "aBBBa" Like "a*a"

' The following statement returns True (does "F" occur in the set of'
'    characters from "A" through "Z"?)'
testCheck = "F" Like "[A-Z]"

' The following statement returns False (does "F" NOT occur in the '
'    set of characters from "A" through "Z"?)'
testCheck = "F" Like "[!A-Z]"

' The following statement returns True (does "a2a" begin and end with'
'    an "a" and have any single-digit number in between?)'
testCheck = "a2a" Like "a#a"

' The following statement returns True (does "aM5b" begin with an "a",'
'    followed by any character from the set "L" through "P", followed'
'    by any single-digit number, and end with any character NOT in'
'    the character set "c" through "e"?)'
testCheck = "aM5b" Like "a[L-P]#[!c-e]"

' The following statement returns True (does "BAT123khg" begin with a'
'    "B", followed by any single character, followed by a "T", and end'
'    with zero or more characters of any type?)'
testCheck = "BAT123khg" Like "B?T*"

' The following statement returns False (does "CAT123khg" begin with'
'    a "B", followed by any single character, followed by a "T", and'
'    end with zero or more characters of any type?)'
testCheck = "CAT123khg" Like "B?T*"

3
czekaj, co? To dla mnie nowość! Hmm, to o wiele lepsze niż alternatywa z manipulacją ciągami VB.NET: D
STW

.. !! Nie wiedziałem o tym, chociaż pracowałem nad kilkoma projektami vb.net! Ciekawa funkcja ...
Meta-Knight

woooooooooooooooooooooooow! dzięki! to jest niesamowite! czy to działa również w ELinq, DLinq? a co z XLinq?
Shimmy Weitzhandler

@dotjoe Hmm? W tych globach nie ma nic „leniwego”.
Josh Lee

Jak to działa, co się dzieje pod maską? Czy to synonim reg ex libraries?
brumScouse

48

Typedefs

VB zna prymitywny rodzaj aliasów typedefvia Import:

Imports S = System.String

Dim x As S = "Hello"

Jest to bardziej przydatne w połączeniu z typami ogólnymi:

Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)

2
Proszę pokazać przykład, że słowo Import nie jest rozpoznawane w moim IDE.
Shimmy Weitzhandler

5
Importspowinno być. ;-) Jakoś ten błąd pozostał niewykryty (i zebrał 28 głosów pozytywnych) przez prawie cały rok.
Konrad Rudolph

Zawsze zastanawiałem się, jak mogę stworzyć nowy „typ” z domyślnymi ustawieniami dla generycznego! Chłodny!
eidylon

3
Import, import, import, cokolwiek! Sheesh, myślisz, że przeczytaliśmy te posty, zanim je zagłosujemy!
MarkJ

Znakomity do używania xunit w testach Visual Studio, tj.Imports Assert = xUnit.Assert
wheelibin

45

O! i nie zapomnij o literałach XML .

Dim contact2 = _
        <contact>
          <name>Patrick Hines</name>
          <%= From p In phoneNumbers2 _
            Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
          %>
        </contact>

To właśnie zamierzałem powiedzieć. W rzeczywistości użyłem literałów XML w celu, do którego nie był przeznaczony. Użyłem go do stworzenia Javascript ... swortham.blogspot.com/2009/03/vb-2008.html
Steve Wortham

9
Możesz między innymi użyć Literałów XML, aby obejść brzydkie znaki ucieczki, np. Gdy używasz łańcuchów, które same zawierają podwójne cudzysłowy. Wystarczy umieścić ciąg wewnątrz XML dosłownym i nazwać wartość, na przykład: <string>This string contains "quotes" and it's OK.</string>.Value (Znalazłem to szczególnie przydatne przy pisaniu testów na parsowanie plików CSV, gdzie każdy polu została w cudzysłowie Byłoby. Nie były zabawy na ucieczkę te wszystkie cytaty ręcznie w moim linie testowe)
Ryan Lundy

2
@Kyralessa: +1, świetny komentarz. W rzeczywistości jest to również świetny sposób na określenie ciągów wieloliniowych (uściski instrukcji SQL itp.).
Heinzi

Inline XML to jedna z najgorszych funkcji VB.NET, jakie kiedykolwiek wymyślono. Nieuzasadniony fakt.
Grant Thomas

39

Inicjalizacja obiektu też jest tam!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}

1
Nie mogę uwierzyć, że poszli z kręconymi szelkami. Mamy już instrukcję With… mogli po prostu ponownie użyć tej składni.
Sam Axe

2
Wiem, to tworzył, aby pokazać, że nie ma policjant na drodze ... lol JK
Shimmy Weitzhandler

4
Tak się dzieje, gdy wszyscy autorzy kompilatorów są w głębi serca programistami C / C ++. Ciągle przenoszą składnię C do innych języków, ponieważ nie mogą sobie wyobrazić nic lepszego.
RBarryYoung

38

DirectCast

DirectCastjest cudem. Na powierzchni działa podobnie do CTypeoperatora, ponieważ konwertuje obiekt z jednego typu na inny. Jednak działa na znacznie bardziej rygorystycznych zasadach. CTypeW związku z tym rzeczywiste zachowanie jest często nieprzejrzyste i nie jest wcale jasne, jaki rodzaj konwersji jest wykonywany.

DirectCast obsługuje tylko dwie różne operacje:

  • Rozpakowanie typu wartości i
  • upcasting w hierarchii klas.

Każde inne rzutowanie nie zadziała (np. Próba rozpakowania Integerdo a Double) i spowoduje błąd kompilacji / czasu wykonania (w zależności od sytuacji i tego, co można wykryć przez statyczne sprawdzanie typu). Dlatego używam, DirectCastgdy tylko jest to możliwe, ponieważ najlepiej oddaje to mój zamiar: w zależności od sytuacji chcę albo rozpakować wartość znanego typu, albo wykonać upcast. Koniec opowieści.

CTypeZ drugiej strony, użycie pozostawia czytelnika z pytaniem o to, co tak naprawdę zamierzał programista, ponieważ rozwiązuje to wszelkiego rodzaju różne operacje, w tym wywoływanie kodu zdefiniowanego przez użytkownika.

Dlaczego jest to ukryta funkcja? Zespół VB opublikował wytyczną 1, która zniechęca do używania DirectCast(mimo że jest w rzeczywistości szybszy!) W celu ujednolicenia kodu. Twierdzę, że jest to zła wskazówka, którą należy odwrócić: jeśli to możliwe, faworyzuj DirectCastbardziej ogólny CTypeoperator. Dzięki temu kod jest znacznie bardziej przejrzysty. CTypez drugiej strony, powinno być wywoływane tylko wtedy, gdy jest to rzeczywiście zamierzone, tj. gdy należy wywołać CTypeoperator zawężający (por. przeciążanie operatorów ).


1) Nie mogę znaleźć linku do wytycznych, ale znalazłem podejście Paula Vicka (głównego programisty zespołu VB):

W prawdziwym świecie prawie nigdy nie zauważysz różnicy, więc równie dobrze możesz wybrać bardziej elastyczne operatory konwersji, takie jak CType, CInt itp.


(EDIT by Zack: Dowiedz się więcej tutaj: Jak przesyłać w VB.NET? )


Trochę bardziej lubię TryCast (). Nie zgłosi wyjątku, po prostu zwróci Nic, jeśli rzutowanie się nie powiedzie. Jeśli spodziewasz się, że rzutowanie często zawiedzie, jest szybsze niż If TypeOf x Is T ... DirectCast (x, T) i na pewno szybsze niż przechwytywanie wyjątku, jeśli DirectCast się nie powiedzie.
Bob King,

6
DirectCast () i TryCast () są nieocenione, gdy są używane poprawnie jako para. DirectCast () powinno być używane, jeśli rzutowany obiekt jest zawsze typem docelowym (jeśli tak nie jest, pojawi się błąd, dobrze, ponieważ jest to nieoczekiwana sytuacja). TryCast () powinno być używane, jeśli rzutowany obiekt może być typu docelowego lub kilku typów docelowych. Używanie jednego lub drugiego na wyłączność doprowadzi do dodatkowego narzutu (jeśli typeof x jest y, to directcast (x, y) jest nieefektywne) lub do uniknięcia prawidłowych błędów (użycie TryCast () w przypadkach, gdy obiekt powinien zawsze być typem docelowym)
STW

Yoooder: w 100% poprawne. To wstyd, o którym wtedy nie wspomniałem, TryCastponieważ miałem głównie kość do skubania przy powszechnym użyciu CType.
Konrad Rudolph

@Maslow: oczywiście, że tak nie jest, ponieważ wyliczenia są typami wartości i TryCastdziałają tylko na typach referencyjnych, zgodnie z dokumentacją.
Konrad Rudolph

+1: Heh. Muszę przyznać, że po prostu to przeczytałem i pomyślałem „O tak, DirectCast, jak o tym zapomniałem?” A potem użyłem go w mojej następnej linii kodu (ponieważ naprawdę nie lubię CType).
RBarryYoung

37

If operator warunkowy i koalescencyjny

Nie wiem, jak można by to nazwać ukrytym, ale funkcja Iif ([wyrażenie], [wartość, jeśli prawda], [wartość, jeśli fałsz]) może liczyć funkcję As Object.

Jest nie tyle ukryty, co przestarzały ! VB 9 ma Ifoperator, który jest znacznie lepszy i działa dokładnie tak, jak operator warunkowy i koalescencyjny C # (w zależności od tego, co chcesz):

Dim x = If(a = b, c, d)

Dim hello As String = Nothing
Dim y = If(hello, "World")

Edytowano, aby pokazać inny przykład:

To zadziała If(), ale spowoduje wyjątek w przypadkuIIf()

Dim x = If(b<>0,a/b,0)

Fajnie, nie wiedziałem tego! Właśnie wczoraj użyłem IIF, więc zamierzam ponownie odwiedzić ten blok kodu.
Sean Gough,

4
Powiedz to VS 2005. Nie każdy z nas może pracować z najnowszymi i najlepszymi.
Sam Erwin,

3
@Slough, bzdury. Ta metoda jest w 100% bezpieczna pod względem typu i zwraca obiekt tego samego typu, co jego (drugi i trzeci) argument. Ponadto musi nastąpić konwersja rozszerzająca między argumentami, w przeciwnym razie wystąpi błąd kompilacji, ponieważ typy nie są zgodne.
Konrad Rudolph

1
Tak, jego IIf () nie jest bezpiecznym typem
Pondidum,

2
@ Br.Bill W rzeczywistości jest to całkowicie odpowiednik:? operatora C i Perla , nie jest to tylko uproszczona wersja.
Konrad Rudolph

32

To jest fajne. Instrukcja Select Case w VB.Net ma bardzo duże możliwości.

Jasne, że jest standard

Select Case Role
  Case "Admin"
         ''//Do X
  Case "Tester"
         ''//Do Y
  Case "Developer"
         ''//Do Z
  Case Else
       ''//Exception case
End Select

Ale jest więcej ...

Możesz robić zakresy:

Select Case Amount
 Case Is < 0
    ''//What!!
 Case 0 To 15
   Shipping = 2.0
 Case 16 To 59
    Shipping = 5.87
 Case Is > 59
    Shipping = 12.50
 Case Else
    Shipping = 9.99
 End Select

I nawet więcej...

Możesz (chociaż może to nie być dobry pomysł) sprawdzać wartości logiczne wielu zmiennych:

Select Case True
 Case a = b
    ''//Do X
 Case a = c
    ''//Do Y
 Case b = c
    ''//Do Z
 Case Else
   ''//Exception case
 End Select

5
Właściwie przegapiłeś kilka: a) użycie „Select Case True” do przetestowania więcej niż jednej zmiennej, b) użycie formularza „Case A, B,…”, a nawet c) zastosowanie „:” do in- wyrównaj instrukcję wykonania klauzulą ​​warunkową (chociaż wielu tego nie lubi).
RBarryYoung

6
Nie używaj opcji Select Case True. Po prostu użyj instrukcji If.
Ryan Lundy

4
Uważam, że Select Case True jest znacznie łatwiejsze do odczytania niż gigantyczne oświadczenie ifelse.
dwidel

Kłopot z Select Case Truejest to, że wygląda tak, jakby ocenia każdy z Casewypowiedzi i uruchamia kod dla każdego z nich, który jest prawdziwy. Ale w rzeczywistości ocenia je pojedynczo i uruchamia kod tylko dla pierwszego, który jest prawdziwy. Pod tym względem składnia for Ifjest znacznie jaśniejsza ( If...Else If...Else If...Else).
Ryan Lundy

31

Jednym z głównych sposobów oszczędzania czasu, których używam cały czas, jest słowo kluczowe With :

With ReallyLongClassName
    .Property1 = Value1
    .Property2 = Value2
    ...
End With

Po prostu nie lubię pisać więcej niż muszę!


Ale tworzy też kilka ukrytych błędów, zwłaszcza gdy masz With within With
Varun Mahajan

2
Nie wiedziałem nawet, że możesz umieścić nowe With w istniejącym With. To po prostu niechlujne!
Bob King,

2Bob: to nie jest niechlujne, sugeruję ... to tylko konstrukcja językowa, której należy używać ostrożnie. Do ustawiania wielu właściwości w kolejnych wierszach jest to świetne, ale znalezienie losowego .Foo w złożonym fragmencie kodu, a następnie konieczność przeszukania linii x instrukcji With powyżej nie jest dobrym zastosowaniem tej funkcji.
ChrisA

2
Chcesz, żeby C # to miał? A może spałem i czy to w odpowiedziach na ukryte funkcje C # już ...? ;-)
peSHIr

1
@Boo: Masz rację, ale nadal jest irytujące, że nie możesz dodać go do listy obserwowanych.
Meta-Knight

31

Najlepszy i łatwy parser CSV:

Microsoft.VisualBasic.FileIO.TextFieldParser

Dodając odniesienie do Microsoft.VisualBasic, można to wykorzystać w dowolnym innym języku .Net, np. C #


5
+1 To dziwne, jak ludzie C # przechodzą do FileHelpers bez zastanowienia się nad tym. Jestem pewien, że FileHelpers jest doskonały, ale jest to zależność zewnętrzna.
MarkJ

@MarkJ Przypuszczam, że to z powodu ignorancji
Nathan Koop

Wygooglowałem do diabła, próbując znaleźć tę klasę i nigdy tego nie zrobiłem, dzięki za to, że to rozpaliłeś!
pingoo


25

Statyczne składowe w metodach.

Na przykład:

Function CleanString(byval input As String) As String
    Static pattern As New RegEx("...")

    return pattern.Replace(input, "")
End Function

W powyższej funkcji wyrażenie regularne wzorca zostanie utworzone tylko raz, bez względu na to, ile razy funkcja zostanie wywołana.

Innym zastosowaniem jest utrzymywanie wystąpienia „losowego” w pobliżu:

Function GetNextRandom() As Integer
    Static r As New Random(getSeed())

    Return r.Next()
End Function 

Nie jest to również to samo, co zwykłe zadeklarowanie go jako współdzielonego członka klasy; Elementy zadeklarowane w ten sposób również są bezpieczne dla wątków. W tym scenariuszu nie ma to znaczenia, ponieważ wyrażenie nigdy się nie zmieni, ale są inne, gdzie może.


1
Jednym z zastosowań tego jest zachowanie licznika, który będzie zwiększał się za każdym razem, gdy wywoływana jest metoda. Jeśli zmienna jest oznaczona jako Static, nie zostanie ponownie zainicjowana przy każdym wywołaniu metody; zostanie zainicjowany tylko przy pierwszym wywołaniu, a później zachowa swoją wartość.
Ryan Lundy

To jest powód, dla którego statyczni członkowie klas są nazywani „współdzielonymi” w VB.NET
Enrico Campidoglio

Static jest w złej formie w VB.NET nawet bardziej niż w klasycznym VB. Zawsze i wszędzie, gdzie to możliwe, należy unikać zmiennych statycznych.
Sam Axe

6
@Boo - to całkiem rozległe. Jakie masz uzasadnienie? Myślę, że zmienne statyczne są przydatne.
MarkJ

4
Statyczny, użyty tak jak w powyższych przykładach, umożliwia unikalną formę hermetyzacji: zmienne na poziomie klasy, które mają zasięg na poziomie metody. Bez tego musiałbyś utworzyć zmienną na poziomie klasy, która byłaby dostępna dla każdego członka klasy, nawet jeśli używasz jej tylko w jednej metodzie.
Ryan Lundy

25

In vb jest różnica między tymi operatorami:

/jest Double
\to Integerpomijając pozostałą

Sub Main()
    Dim x = 9 / 5  
    Dim y = 9 \ 5  
    Console.WriteLine("item x of '{0}' equals to {1}", x.GetType.FullName, x)
    Console.WriteLine("item y of '{0}' equals to {1}", y.GetType.FullName, y)

    'Results:
    'item x of 'System.Double' equals to 1.8
    'item y of 'System.Int32' equals to 1
End Sub

1
Nauczyłem się tego na własnej skórze, próbując znaleźć igłę w milionie linii kodu. dzielenie zwykłe i całkowite. dobra wskazówka!
Jason Irwin

23

Bardzo podoba mi się „My” Namespace, która została wprowadzona w Visual Basic 2005. My to skrót do kilku grup informacji i funkcji. Zapewnia szybki i intuicyjny dostęp do następujących rodzajów informacji:

  • My.Computer : Dostęp do informacji związanych z komputerem, takich jak system plików, sieć, urządzenia, informacje o systemie itp. Zapewnia dostęp do wielu bardzo ważnych zasobów, w tym My.Computer.Network, My.Computer.FileSystem i My .Komputer.Drukarki.
  • My.Application : dostęp do informacji związanych z daną aplikacją, takich jak nazwa, wersja, aktualny katalog itp.
  • My.User : Dostęp do informacji związanych z aktualnie uwierzytelnionym użytkownikiem.
  • My.Resources : dostęp do zasobów używanych przez aplikację, znajdujących się w plikach zasobów w sposób jednoznacznie określony .
  • My.Settings : Dostęp do ustawień konfiguracyjnych aplikacji w sposób jednoznacznie określony .

To jest po prostu świetne i każdy facet vb.net powinien wiedzieć rzeczy z mojej przestrzeni nazw, jest to bardzo przydatne.
dr. zło

Mój. * FTW :).
dr. zły

3
To trochę przydatne, ale nienawidzę tej głupiej nazwy. Przypomina mi to secretgeek.net/refactvb.asp
MarkJ

23

Zdarzenia niestandardowe

Chociaż rzadko jest przydatna, obsługa zdarzeń może być mocno dostosowana:

Public Class ApplePie
    Private ReadOnly m_BakedEvent As New List(Of EventHandler)()

    Custom Event Baked As EventHandler
        AddHandler(ByVal value As EventHandler)
            Console.WriteLine("Adding a new subscriber: {0}", value.Method)
            m_BakedEvent.Add(value)
        End AddHandler

        RemoveHandler(ByVal value As EventHandler)
            Console.WriteLine("Removing subscriber: {0}", value.Method)
            m_BakedEvent.Remove(value)
        End RemoveHandler

        RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
            Console.WriteLine("{0} is raising an event.", sender)
            For Each ev In m_BakedEvent
                ev.Invoke(sender, e)
            Next
        End RaiseEvent
    End Event

    Public Sub Bake()
        ''// 1. Add ingredients
        ''// 2. Stir
        ''// 3. Put into oven (heated, not pre-heated!)
        ''// 4. Bake
        RaiseEvent Baked(Me, EventArgs.Empty)
        ''// 5. Digest
    End Sub
End Class

Można to następnie przetestować w następujący sposób:

Module Module1
    Public Sub Foo(ByVal sender As Object, ByVal e As EventArgs)
        Console.WriteLine("Hmm, freshly baked apple pie.")
    End Sub

    Sub Main()
        Dim pie As New ApplePie()
        AddHandler pie.Baked, AddressOf Foo
        pie.Bake()
        RemoveHandler pie.Baked, AddressOf Foo
    End Sub
End Module

wydaje się fajne, ale jeśli kiedykolwiek będę tego potrzebować, myślę, że zrobię coś złego ;-). Wydaje się to po prostu sprzeczne z zasadą KISS.
chrissie1

4
Jest to naprawdę przydatne, gdy chcesz mieć pewność, że każdy element sink otrzyma zdarzenie, nawet jeśli co najmniej jeden zgłosi wyjątek.
Jonathan Allen

Inną wartością (właśnie przeczytałem to w witrynie MSDN) jest to, że jeśli Twoja klasa generuje wiele zdarzeń, możesz zmusić ją do używania tabeli / słownika skrótów jako kontenera, zamiast deklarować pole dla każdego zdarzenia. msdn.microsoft.com/en-us/library/8627sbea(VS.71).aspx
torial

Chłodny. Pomyślałem, że to jedna z funkcji, która wyróżnia C # i VB.NET (jak w jednej, ale druga nie ma dla niej składni). Miło przynajmniej wiedzieć, że się myliłem w tej kwestii.
peSHIr

21

Właśnie znalazłem artykuł mówiący o „!” operator, zwany także „operatorem wyszukiwania w słowniku”. Oto fragment artykułu pod adresem : http://panopticoncentral.net/articles/902.aspx

Techniczna nazwa! operator jest „operatorem wyszukiwania w słowniku”. Słownik to dowolny typ zbioru, który jest indeksowany za pomocą klucza, a nie liczby, tak jak sposób, w jaki wpisy w słowniku angielskim są indeksowane według słowa, którego definicję chcesz zdefiniować. Najpopularniejszym przykładem typu słownika jest System.Collections.Hashtable, który umożliwia dodawanie par (klucz, wartość) do tablicy hashy, a następnie pobieranie wartości za pomocą kluczy. Na przykład poniższy kod dodaje trzy wpisy do tablicy hashy i wyszukuje jeden z nich za pomocą klucza „Pork”.

Dim Table As Hashtable = New Hashtable
Table("Orange") = "A fruit"
Table("Broccoli") = "A vegetable"
Table("Pork") = "A meat" 
Console.WriteLine(Table("Pork"))

The! operator może służyć do wyszukiwania wartości z dowolnego typu słownika, który indeksuje wartości przy użyciu ciągów. Identyfikator po! jest używany jako klucz w operacji wyszukiwania. Zatem powyższy kod mógłby zostać napisany:

Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
Console.WriteLine(Table!Pork)

Drugi przykład jest całkowicie równoważny z pierwszym, ale po prostu wygląda o wiele ładniej, przynajmniej w moich oczach. Uważam, że jest wiele miejsc, w których! może być używany, zwłaszcza jeśli chodzi o XML i Internet, gdzie jest tylko mnóstwo kolekcji indeksowanych przez ciąg. Jednym niefortunnym ograniczeniem jest to, że rzecz następująca po! nadal musi być prawidłowym identyfikatorem, więc jeśli ciąg, którego chcesz użyć jako klucza, zawiera jakiś nieprawidłowy znak identyfikacyjny, nie możesz użyć! operator. (Nie możesz na przykład powiedzieć „Tabela! AB $ CD = 5”, ponieważ $ nie jest legalne w identyfikatorach). W wersji VB6 i wcześniejszych można używać nawiasów, aby uniknąć nieprawidłowych identyfikatorów (np. „Tabela! [AB $ CD] ”), ale kiedy zaczęliśmy używać nawiasów do zastępowania słów kluczowych, straciliśmy możliwość tego. W większości przypadków,

Aby uzyskać naprawdę techniczne, x! Y działa, jeśli x ma domyślną właściwość, która przyjmuje String lub Object jako parametr. W takim przypadku x! Y jest zamieniane na x.DefaultProperty ("y"). Ciekawostką na marginesie jest to, że w gramatyce leksykalnej języka istnieje specjalna reguła, która sprawia, że ​​to wszystko działa. The! znak jest również używany jako znak typu w języku, a znaki typu są spożywane przed operatorami. Zatem bez specjalnej reguły x! Y byłby skanowany jako „x! Y” zamiast „x! Y”. Na szczęście, ponieważ w języku nie ma miejsca, w którym dwa identyfikatory w wierszu byłyby prawidłowe, wprowadziliśmy właśnie regułę, że jeśli następny znak po! jest początkiem identyfikatora, rozważamy! być operatorem, a nie znakiem typu.


11
To jedna z tych funkcji, których użyłem, a potem celowo zapomniałem. Oszczędza kilka naciśnięć klawiszy, ale psuje mój kod podświetlania i czytelności. znowu zapominając dobrze .... TERAZ
STW

3
Ciekawe, ale mało przydatne. Czy jest to rodzaj rzeczy, nad którymi pracuje zespół VB zamiast dodawać brakujące funkcje, takie jak słowo kluczowe yield? : P
Meta-Knight

5
Ta funkcja jest przenoszona w celu zapewnienia wstecznej kompatybilności z VB3 (AFAIK)
Eduardo Molteni

1
czy te klasy, które implementują indeks z kluczem, mają wspólny interfejs, z którego dziedziczą? jak IKeyed w ten sam sposób, w jaki kontenery indeksowane liczbami całkowitymi implementują IENumberable?
Maslow

2
Ta funkcja działa również z DataRows (tj. Dr! ID), co jest BARDZO przydatne w LINQ to DataSets.
Paul

19

Jest to wbudowane i stanowi zdecydowaną przewagę nad C #. Możliwość zaimplementowania metody interfejsu bez konieczności używania tej samej nazwy.

Jak na przykład:

Public Sub GetISCSIAdmInfo(ByRef xDoc As System.Xml.XmlDocument) Implements IUnix.GetISCSIInfo

End Sub

Jestem pewien, że możesz zrobić coś takiego w C #. W VB.NET jest to wymuszone, aw C # opcjonalne?
Jesper Blad Jensen

5
Możesz również ustawić sub-prywatny, co jest świetnym sposobem na ukrycie rzeczy, takich jak wywołania nieogólnych, przestarzałych wersji interfejsów.
Craig Gidney

3
To może być dobry pomysł. Klasycznym przykładem byłoby, gdybyś potrzebowała metody Public Close, która działa również jako implementacja Dispose dla IDisposable.
MarkJ

1
Jest to również przydatne, jeśli zdarzy ci się zaimplementować dwa interfejsy, które mają wspólną nazwę metody.
Eric Nicholson,

Widziałem to i zawsze żałuję, że tego nie widziałem. Nie powinno być dozwolone.
FastAl,

17

Wymuszanie ByVal

W VB, jeśli zawiniesz swoje argumenty w dodatkowym zestawie nawiasów, możesz przesłonić deklarację ByRef metody i przekształcić ją w ByVal. Na przykład poniższy kod daje 4, 5, 5 zamiast 4,5,6

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim R = 4
    Trace.WriteLine(R)
    Test(R)
    Trace.WriteLine(R)
    Test((R))
    Trace.WriteLine(R)
End Sub
Private Sub Test(ByRef i As Integer)
    i += 1
End Sub

Zobacz Argument niezmodyfikowany przez wywołanie procedury - zmienna bazowa


6
O mój Boże ... to niezwykła funkcja, chociaż nie sądzę, żebym wiedział, co robi, gdybym przeczytał ją w czyimś kodzie. Jeśli musisz to skomentować, aby wiedzieć, co robi, równie dobrze mógłbyś zamiast tego przekazać zmienną odrzucenia.
mattmc3

7
W rzeczywistości jest to efekt uboczny użycia nawiasów - nawiasy tworzą tymczasową wartość tego, co jest w środku, nawet jeśli jest to tylko jeden element. Ten efekt KILLED ME in vb6 - Sub wywołania nie przyjmowały parenów, ale ja pochodząc z C instynktownie wstawiłem pareny. 6.0 wysadził na wielu parametrach, ale dla jednego parametru podrzędnego szczęśliwie przekazał wartość tymczasową i ODMOWA, aby uhonorować moje „byref”. Zdarzało się mniej więcej co 3 lata, mniej więcej tyle czasu zajęło mi zapomnienie ostatniego incydentu.
FastAl,

16

Przekazywanie parametrów według nazwy i zmiana ich kolejności

Sub MyFunc(Optional msg as String= "", Optional displayOrder As integer = 0)

    'Do stuff

End function

Stosowanie:

Module Module1

    Sub Main()

        MyFunc() 'No params specified

    End Sub

End Module

Można go również wywołać przy użyciu specyfikacji parametru „: =” w dowolnej kolejności:

MyFunc(displayOrder:=10, msg:="mystring")

Wow, to jest super fajne! Widziałem to podczas korzystania z usług sieciowych itp., Ale nie wiedziałem, że możesz to zrobić jakąkolwiek starą normalną metodą.
RichC

2
Zdecydowanie bardzo przydatne narzędzie, gdy napotkasz metodę, która wymaga zbyt wielu argumentów. Próbuję nazwać każdy parametr i umieścić nazwę: = wartość w osobnym wierszu. Jest o wiele bardziej intuicyjny i przejrzysty w przypadku metod, które przyjmują> 5 (moja praktyczna zasada) parametrów.
STW

Szczególnie przydatny do automatyzacji Office, gdzie trzeba radzić sobie z metodami z dziesiątkami opcjonalnych argumentów.
MarkJ

1
Fajne jest również to, że możesz połączyć te dwa elementy: zacznij od określenia wymaganych parametrów w kolejności, a następnie przełącz się na nazwane parametry dla opcjonalnych argumentów!
RBarryYoung

15

Instrukcja Using jest nowa od wersji VB 8, C # miała ją od początku. Wzywa do automatycznego usuwania.

Na przykład

Using lockThis as New MyLocker(objToLock)

End Using

23
Warto zauważyć (tylko dlatego, że zapomniałem co najmniej dwa razy), że możesz mieć jedną instrukcję Using zawija kilka obiektów jednorazowego użytku. Składnia jest następująca: „Użycie objA jako nowego obiektu, objB jako nowego obiektu ....” Jest o wiele czystsze niż zagnieżdżanie wielu instrukcji Using.
STW

Na pewno jeden z moich ulubionych.
Sam Axe

14

Aliasy importu są również w dużej mierze nieznane:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form

1
Myślę, że mieliśmy ten sam pomysł.
chrissie1

3
@Boo - oto prosty przykład, w którym aliasy importu nie są złe. stackoverflow.com/questions/92869/…
torial

W porządku - istnieje oczywista droga do nadużyć, ale niezależnie od rant @ torial jest to świetna funkcja. Za każdym razem, gdy dołączam System.Text.RegularExpressions, ryzykuję kolizję nazw z klasą „Group”, ponieważ jest to wspólna nazwa klasy. Alias ​​pozwala uniknąć konieczności pełnego kwalifikowania niejednoznacznych klas, co pozwala zaoszczędzić dużo czasu i faktycznie poprawia czytelność, gdy jest używane prawidłowo. Ta funkcja jest świetna, ale twój konkretny przykład w pewnym sensie zachęca do kpiny - przepraszam za to.
mattmc3

14

Rozważ następującą deklarację zdarzenia

Public Event SomethingHappened As EventHandler

W języku C # można sprawdzić, czy subskrybenci zdarzeń są dostępni przy użyciu następującej składni:

if(SomethingHappened != null)
{
  ...
}

Jednak kompilator VB.NET tego nie obsługuje. W rzeczywistości tworzy ukryte prywatne pole członkowskie, które nie jest widoczne w IntelliSense:

If Not SomethingHappenedEvent Is Nothing OrElse SomethingHappenedEvent.GetInvocationList.Length = 0 Then
...
End If

Więcej informacji:

http://jelle.druyts.net/2003/05/09/BehindTheScenesOfEventsInVBNET.aspx http://blogs.msdn.com/vbteam/archive/2009/09/25/testing-events-for-nothing-null-doug -rothaus.aspx


Dlaczego miałbyś kiedykolwiek chcieć to zrobić? Nie wyobrażam sobie przypadku użycia, w którym trzeba znać liczbę subskrybentów wydarzenia w VB.
Konrad Rudolph

W pewnych okolicznościach C # zgłasza wyjątek, jeśli zgłosisz zdarzenie i nie ma żadnych programów obsługi. VB.Net tego nie zrobi. Stąd potrzeba sprawdzenia.
Joel Coehoorn,

2
Użyłem tego dla zdarzenia obiektu biznesowego, które podniosło komunikaty o błędach walidacji do subskrybentów. Chciałem sprawdzić, czy zdarzenie jest obsługiwane, aby wiedzieć, że otrzymywane są błędy walidacji. W przeciwnym razie obiekt biznesowy zgłosił wyjątek.
Technobabble,

2
Innym przydatnym zastosowaniem tego prywatnego członka jest pobranie listy wywołań wydarzenia. Użyłem go w kilku przypadkach do wywołania zdarzenia w sposób asynchroniczny do wszystkich wywołujących (zapobiega modyfikowaniu zdarzenia przez odbiorcę A przed jego odebraniem; zapobiega również opóźnianiu dostarczenia przez odbiornik A do odbiornika B). Używałem tego często w niestandardowych scenariuszach synchronizacji danych, a także w interfejsach API.
STW

14

Jeśli chcesz, aby nazwa zmiennej pasowała do słowa kluczowego, umieść ją w nawiasach. Nie gdzie indziej. najlepsza praktyka - ale można ją mądrze stosować.

na przykład

Class CodeException
Public [Error] as String
''...
End Class

''later
Dim e as new CodeException
e.Error = "Invalid Syntax"

np. przykład z komentarzy (@Pondidum):

Class Timer
Public Sub Start()
''...
End Sub

Public Sub [Stop]()
''...
End Sub

Myślę, że ten przykład byłby lepszy, gdybyś nie użył „If” jako przykładowego słowa kluczowego.
Sean Gough,

4
timer.Start and timer.Stop przychodzą na myśl jako przykłady dobrego wykorzystania tego
Pondidum

5
+1 za wskazanie tego z zastrzeżeniem. Istnieje kilka klas frameworka, które wymagają tego do poprawnego rozwiązania, np. [Assembly]
STW

5
[Enum] to kolejny dobry przykład przypadku, w którym potrzebujesz nawiasów, aby użyć klasy zamiast słowa kluczowego.
Ryan Lundy

13

Istnieje kilka odpowiedzi dotyczących literałów XML, ale nie dotyczących tego konkretnego przypadku:

Możesz użyć literałów XML, aby ująć literały ciągów, które w innym przypadku wymagałyby zmiany znaczenia. Na przykład literały ciągów zawierające cudzysłowy.

Zamiast tego:

Dim myString = _
    "This string contains ""quotes"" and they're ugly."

Możesz to zrobić:

Dim myString = _
    <string>This string contains "quotes" and they're nice.</string>.Value

Jest to szczególnie przydatne, jeśli testujesz literał do analizy CSV:

Dim csvTestYuck = _
    """Smith"", ""Bob"", ""123 Anywhere St"", ""Los Angeles"", ""CA"""

Dim csvTestMuchBetter = _
    <string>"Smith", "Bob", "123 Anywhere St", "Los Angeles", "CA"</string>.Value

(Oczywiście nie musisz używać <string>tagu; możesz użyć dowolnego tagu, który chcesz).


3
<q>byłby dobrym tagiem, podobnym do użycia w Perlu / Ruby. W każdym razie to całkiem niezły idiom. LUBIĆ!
Konrad Rudolph

Co za genialny pomysł. Dziękuję
Jeremy

12

DateTime można zainicjować, otaczając datę #

Dim independanceDay As DateTime = #7/4/1776#

Możesz również użyć wnioskowania o typie razem z tą składnią

Dim independanceDay = #7/4/1776#

To o wiele przyjemniejsze niż użycie konstruktora

Dim independanceDay as DateTime = New DateTime(1776, 7, 4)

6
Nie, jeśli masz Option Strict On
danlash

12

Możesz mieć 2 linie kodu w jednej linii. W związku z tym:

Dim x As New Something : x.CallAMethod

whoa ... myślałem, że to możliwe tylko z klasą i dziedziczeniem
Jason

Nie zapomnijCall (New Something).CallAMethod()
Jonathan Allen

To jest holdever z MS-Basic na Apple] [! W moim sklepie byłbym tak samo wyśmiewany za używanie Gotos: - /
FastAl

W większości przypadków należy tego unikać, ale lubię używać tego w przypadku stwierdzeń przypadków, w których linie są naprawdę krótkie, np. Przypadek 4: x = 22
dwidel

11

Parametry opcjonalne

Opcje są o wiele łatwiejsze niż tworzenie nowych przeciążeń, takich jak:

Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
   Console.Writeline(msg)
   ''//do stuff
End Function

1
Nie wiedziałem, że C # je dostanie. Są ładne, ale musisz uważać, aby używać ich tylko wtedy , gdy masz pewność, że kod nie zostanie wykorzystany przez C #, ponieważ ich nie obsługuje. FxCop / Code Analysis powie ci zamiast tego przeciążenie metody.
STW

... Właśnie znalazłem świetne zastosowanie dla parametrów opcjonalnych, jednocześnie utrzymując je poza kodem produkcyjnym. Napisałem o tym krótki post na mojej stronie: yoooder.com/wordpress/?p=62
STW

2
Ach, tak bardzo tym gardzę ... Ale przydatne do automatyzacji pakietu Office
dance2die

9

Przypadek tytułu w VB.Net można uzyskać za pomocą starego fxn VB6:

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID

1
jest również w klasie textinfo. nie jestem pewien, w jakiej przestrzeni nazw się znajduje. Prawdopodobnie system.text
Shawn,

Lepiej jest być neutralnym językowo .NET i używać klasy Globalization TextInfo do konwersji ToTitleCase. Jeśli kiedykolwiek kod będzie musiał zostać przekonwertowany na C #, będziesz mieć wiele drobiazgów, które wymagają Microsoft.VisualBasic
Jeremy

9

Właściwości z parametrami

Zajmowałem się programowaniem w C # i odkryłem brakującą funkcję, którą miał VB.Net, ale nie została tutaj wspomniana.

Przykład, jak to zrobić (a także ograniczenie języka C # ) można zobaczyć na stronie: Używanie typowych właściwości get set w C # ... with parameters

Wyciągnąłem kod z tej odpowiedzi:

Private Shared m_Dictionary As IDictionary(Of String, Object) = _
             New Dictionary(Of String, Object)

Public Shared Property DictionaryElement(ByVal Key As String) As Object
    Get
        If m_Dictionary.ContainsKey(Key) Then
            Return m_Dictionary(Key)
        Else
            Return [String].Empty
        End If
    End Get
    Set(ByVal value As Object)
        If m_Dictionary.ContainsKey(Key) Then
            m_Dictionary(Key) = value
        Else
            m_Dictionary.Add(Key, value)
        End If

    End Set
End Property

Jest to interesujące, ale nie jestem do końca pewien, gdzie byłoby to przydatne. myObj.Something ("abc") bardziej przypomina dostęp do funkcji niż do właściwości. Nie wiem, co to kupuje.
mattmc3

Nienawidzę dwuznaczności. Co to powinno być. Metoda lub właściwość. Niektóre narzędzia refaktoringu Proponuję stworzenie zarówno w pewnych sytuacjach też, wygląda na to, że nawet nie wiem ...
brumScouse
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.