Historia pytania:
Zagnieżdżone procedury (local functions) w Visual Basic pojawiły się dopiero w wersjach VB.NET zaczynając od VB 15.0 (Visual Studio 2017), co odróżnia je od klasycznego VB6, gdzie taka możliwość nie istniała. Ta cecha pozwala na deklarowanie procedur wewnątrz innych procedur, co poszerza wyrazistość języka i upraszcza organizację logiki pomocniczej w jednej widoczności.
Problem
Częste sytuacje, gdy pewna logika pomocnicza jest potrzebna tylko wewnątrz konkretnej metody i nie jest wymagana nigdzie indziej. Wcześniej konieczne było tworzenie prywatnych metod klasy, co zwiększało zanieczyszczenie przestrzeni nazw i utrudniało nawigację w kodzie. Lecz nawet w przypadku local functions łatwo napotkać problemy z zakresem widoczności, błędami dostępu do zmiennych i trudnościami w debugowaniu.
Rozwiązanie
Zagnieżdżone procedury pozwalają na inkapsulację logiki pomocniczej w „rodzicielskiej” procedurze, czyniąc kod bardziej czytelnym i ograniczając zakres widoczności metod pomocniczych. W VB.NET deklaracja zagnieżdżonych funkcji wygląda tak:
Sub MainProc() Dim x As Integer = 5 Dim y As Integer = 10 Console.WriteLine($"Suma — {Add(x, y)}") Function Add(a As Integer, b As Integer) As Integer Return a + b End Function End Sub
Kluczowe cechy:
Czy zagnieżdżone procedury mogą mieć modyfikatory dostępu Public, Friend lub Protected?
Nie, dla zagnieżdżonych procedur dozwolony jest tylko poziom dostępności wewnątrz ich „rodzicielskiej” procedury. Nie mogą być deklarowane jako Public/Friend/Protected i są dostępne tylko lokalnie.
Czy można zadeklarować zagnieżdżoną procedurę w konstrukcji For lub If?
Nie, lokalne funkcje można deklarować tylko na pierwszym poziomie wewnątrz metody (procedury), ale nie wewnątrz zagnieżdżonych bloków (np. For, If, While).
Czy zagnieżdżone procedury mogą być asynchroniczne (Async Sub/Function)?
Tak, można deklarować asynchroniczne lokalne funkcje, co pozwala na inkapsulację logiki asynchronicznego wykonania wewnątrz metody:
Async Sub DoOperationsAsync() Await LocalAsync() Async Function LocalAsync() As Task Await Task.Delay(1000) Console.WriteLine("Operacja asynchroniczna zakończona.") End Function End Sub
W projekcie nadmiarowo używano prywatnych metod zamiast lokalnych funkcji, przez co dziesiątki procedur pomocniczych „zasmrodziły” interfejs klasy. Nawigacja znacząco się utrudniła.
Plusy:
Minusy:
Dla wewnętrznej logiki zastosowano podejście z lokalnymi funkcjami: cała obsługa pomocnicza została umieszczona wewnątrz głównej metody, kod jest samo-dokumentujący, łatwy w utrzymaniu.
Plusy:
Minusy: