SlideShare a Scribd company logo
Visual Basic 2005.
                           Almanach
                           Tim Patrick, Steven Roman, Ron Petrusha, Paul Lomax
                           T³umaczenie: Miko³aj Szczepaniak
                           ISBN: 83-246-0475-8
                           Tytu³ orygina³u: Visual Basic 2005 in a Nutshell
                           Format: B5, stron: 880
                           Przyk³ady na ftp: 7 kB




                           Visual Basic po raz pierwszy pojawi³ siê na rynku w roku 1991 jako po³¹czenie
                           oferowanego przez Microsoft jêzyka QBasic z mechanizmem projektowania graficznego
                           interfejsu u¿ytkownika. Od tej pory przeszed³ spor¹ ewolucjê, zyskuj¹c jednoczeœnie
                           ogromne grono zwolenników. W roku 2001 wprowadzono na rynek platformê
                           programistyczn¹ .NET wraz z ca³kowicie zmienion¹ i odnowion¹ wersj¹ Visual Basica
                           pod nazw¹ Visual Basic .NET. Visual Basic dla platformy .NET by³ jêzykiem w pe³ni
                           obiektowym i oferowa³ znacznie wiêksze mo¿liwoœci ni¿ jego poprzednicy. Visual Basic
                           2005 to najnowsze wcielenie tego popularnego jêzyka programowania.
                           Ksi¹¿ka „Visual Basic 2005. Almanach” to kompleksowe omówienie wszystkich
                           zagadnieñ zwi¹zanych z programowaniem w tym jêzyku. Czytaj¹c j¹, poznasz genezê
                           platformy .NET, jej sk³adniki i konstrukcjê oraz s³owa kluczowe jêzyka Visual Basic.
                           Przeczytasz o programowaniu obiektowym, klasach platformy .NET, obs³udze zdarzeñ
                           oraz typach uniwersalnych. Dalsza czêœæ ksi¹¿ki to niezwykle przydatne ka¿demu
                           programiœcie zestawienie dokumentacji wszystkich istotnych wyra¿eñ, procedur, funkcji
                           i obiektów Visual Basica zawieraj¹ce omówienie sk³adni i argumentów, wskazówki
                           dotycz¹ce sposobu stosowania omawianego elementu jêzyka, przyk³ady kodu oraz
                           opisy nieudokumentowanych zachowañ.
                           W ksi¹¿ce omówiono:
                               • Podstawowe wiadomoœci o platformie .NET
                               • Zasady programowania obiektowego
                               • Zmienne, typy danych i operatory
                               • Struktura programów w Visual Basic
                               • Klasy platformy .NET
                               • Typy uniwersalne
Wydawnictwo Helion             • Obs³uga b³êdów i wyj¹tków
ul. Koœciuszki 1c              • Leksykon elementów jêzyka Visual Basic 2005
44-100 Gliwice                          Zostañ ekspertem w dziedzinie programowania w Visual Basicu
tel. 032 230 98 63
e-mail: helion@helion.pl
Spis treści



     Przedmowa ................................................................................................................... 21

I Podstawy .................................................................................................29
1. Wprowadzenie .............................................................................................................. 31
     Dlaczego Visual Basic .NET?                                                                                                 32
     Czym jest Visual Basic .NET?                                                                                                36
     Co możemy zrobić w środowisku Visual Basic .NET?                                                                            42
     Wersje języka Visual Basic .NET                                                                                             43

2. Platforma .NET Framework: pojęcia ogólne ................................................................45
     Środowisko uruchomieniowe wspólnego języka                                                                                  45
     Kod zarządzany                                                                                                              46
     Przestrzenie nazw                                                                                                           47
     Typy i obiekty                                                                                                              48
     Podzespoły                                                                                                                  49
     Biblioteka klas platformy .NET (FCL)                                                                                        51
     Wdrażanie aplikacji                                                                                                         52
     Platforma .NET i język Visual Basic                                                                                         52

3. Wprowadzenie do programowania obiektowego .....................................................53
     Reguły programowania obiektowego                                                                                            53
     Programowanie obiektowe w języku Visual Basic                                                                               58

4. Zmienne i typy danych .................................................................................................. 77
     Typy danych                                                                                                                77
     Zmienne                                                                                                                    93
     Stałe                                                                                                                      97
     Typy wyliczeniowe                                                                                                          98
     Tablice                                                                                                                    98
     Kolekcje                                                                                                                   99
     Parametry i argumenty                                                                                                     100

                                                                                                                                   3
5. Operatory .................................................................................................................... 105
            Operatory arytmetyczne                                                                                                    105
            Operatory konkatenacji                                                                                                    107
            Operatory logiczne i bitowe                                                                                               107
            Operatory przypisania                                                                                                     112
            Operatory porównania                                                                                                      114
            Operatory obiektowe                                                                                                       115
            Przeciążanie operatorów                                                                                                   117
            Priorytety operatorów                                                                                                     119

     6. Struktura programu .....................................................................................................121
            Rodzaje aplikacji tworzonych w środowisku Visual Studio                                                                   121
            Techniki odwołań do komponentów i klas                                                                                    122
            Punkty wejścia aplikacji                                                                                                  123
            Zawartość pliku z kodem źródłowym                                                                                         126
            Struktura programu Visual Basica                                                                                          127

     7. Biblioteka klas platformy .NET ................................................................................... 135
            Przestrzeń nazw System                                                                                                    136
            Przestrzeń nazw System.Collections                                                                                        142
            Przestrzeń nazw System.Data                                                                                               142
            Przestrzeń nazw System.IO                                                                                                 143
            Przestrzeń nazw System.Text.RegularExpressions                                                                            144
            Przestrzeń nazw System.Windows.Forms                                                                                      146
            Pozostałe przestrzenie nazw                                                                                               146

     8. Delegacje i zdarzenia .................................................................................................. 149
            Delegacje                                                                                                                 150
            Zdarzenia i wiązanie zdarzeń                                                                                              153

     9. Atrybuty ...................................................................................................................... 159
            Składnia i techniki stosowania                                                                                            160
            Definiowanie atrybutów niestandardowych                                                                                   163
            Korzystanie z atrybutów niestandardowych                                                                                  166

    10. Typy uniwersalne .........................................................................................................171
            Czym są typy uniwersalne?                                                                                                 171
            Parametry typów                                                                                                           172
            Stosowanie wielu parametrów typów                                                                                         173
            Ograniczenia                                                                                                              173
            Ograniczenia złożone                                                                                                      174
            Uzyskiwanie dostępu do składowych parametrów typów                                                                        175


4       |    Spis treści
Metody uniwersalne                                                                                                177
      Zagnieżdżone typy uniwersalne                                                                                     177
      Typy i składowe przeciążone                                                                                       177

11. Obsługa błędów w Visual Basicu ............................................................................... 179
      Wykrywanie i obsługa błędów                                                                                       179
      Obsługa błędów wykonywania                                                                                        180
      Obsługa błędów logiki                                                                                             188
      Stałe błędów                                                                                                      191


II Leksykon ................................................................................................ 193
12. Leksykon języka Visual Basic ...................................................................................... 195
      #Const (dyrektywa)                                                                                                197
      #If...Then...#Else (dyrektywa)                                                                                    198
      #Region...#End Region (dyrektywa)                                                                                 200
      Abs (funkcja)                                                                                                     200
      Acos (funkcja)                                                                                                    201
      AddHandler (wyrażenie)                                                                                            202
      AddressOf (operator)                                                                                              203
      AppActivate (procedura)                                                                                           203
      Application (klasa)                                                                                               205
      Application.CompanyName (właściwość)                                                                              206
      Application.DoEvents (metoda)                                                                                     207
      Application.ExecutablePath (właściwość)                                                                           208
      Application.ProductName (właściwość)                                                                              209
      Application.ProductVersion (właściwość)                                                                           209
      Application.Run (metoda)                                                                                          210
      Array (klasa)                                                                                                     211
      Array.BinarySearch (metoda)                                                                                       212
      Array.Copy (metoda)                                                                                               214
      Array.IndexOf (metoda)                                                                                            215
      Array.LastIndexOf (metoda)                                                                                        216
      Array.Reverse (metoda)                                                                                            217
      Array.Sort (metoda)                                                                                               218
      Asc i AscW (funkcje)                                                                                              220
      AssemblyVersion (atrybut)                                                                                         220
      Asin (funkcja)                                                                                                    221
      Atan (funkcja)                                                                                                    222
      Atan2 (funkcja)                                                                                                   223
      AttributeUsage (atrybut)                                                                                          224
      Beep (procedura)                                                                                                  225

                                                                                                      Spis treści   |     5
Call (wyrażenie)                225
        CallByName (funkcja)            226
        CBool (funkcja)                 228
        CByte (funkcja)                 228
        CChar (funkcja)                 229
        CDate (funkcja)                 230
        CDbl (funkcja)                  231
        CDec (funkcja)                  231
        Ceiling (funkcja)               232
        ChDir (procedura)               233
        ChDrive (procedura)             234
        Choose (funkcja)                235
        Chr i ChrW (funkcje)            237
        CInt (funkcja)                  238
        Class...End Class (wyrażenie)   239
        Clipboard (klasa)               241
        CLng (funkcja)                  241
        CLSCompliant (atrybut)          242
        CObj (funkcja)                  243
        Collection (klasa)              244
        Collection.Add (metoda)         245
        Collection.Count (właściwość)   247
        Collection.Item (właściwość)    248
        Collection.Remove (metoda)      248
        ColorDialog (klasa)             249
        COMClass (atrybut)              251
        Command (funkcja)               252
        Const (wyrażenie)               254
        Continue (wyrażenie)            255
        Cos (funkcja)                   256
        Cosh (funkcja)                  257
        CreateObject (funkcja)          257
        CSByte (funkcja)                259
        CShort (funkcja)                260
        CSng (funkcja)                  261
        CStr (funkcja)                  262
        CType (funkcja)                 263
        CUInt (funkcja)                 265
        CULng (funkcja)                 266
        CUShort (funkcja)               267
        CurDir (funkcja)                268
        Custom Event (wyrażenie)        268

6   |    Spis treści
DateAdd (funkcja)                                           270
DateDiff (funkcja)                                          272
DatePart (funkcja)                                          274
DateSerial (funkcja)                                        276
DateString (właściwość)                                     277
DateValue (funkcja)                                         278
Day (funkcja)                                               278
DDB (funkcja)                                               279
Debug (klasa)                                               280
Debug.Assert (metoda)                                       282
Debug.Listeners (właściwość)                                283
Debug.Write (metoda)                                        284
Debug.WriteIf (metoda)                                      284
Debug.WriteLine (metoda)                                    285
Debug.WriteLineIf (metoda)                                  286
Declare (wyrażenie)                                         287
DefaultMember (atrybut)                                     290
Delegate (wyrażenie)                                        292
DeleteSetting (procedura)                                   294
Dim (wyrażenie)                                             296
Dir (funkcja)                                               300
DirectCast (funkcja)                                        302
Directory (klasa)                                           303
Directory.CreateDirectory (metoda)                          304
Directory.Delete (metoda)                                   305
Directory.Exists (metoda)                                   306
Directory.GetCreationTime (metoda)                          307
Directory.GetDirectories (metoda)                           307
Directory.GetDirectoryRoot (metoda)                         309
Directory.GetFiles (metoda)                                 310
Directory.GetFileSystemEntries (metoda)                     311
Directory.GetLogicalDrives (metoda)                         312
Directory.GetParent (metoda)                                313
Directory.Move (metoda)                                     314
Do...Loop (wyrażenie)                                       315
E (pole)                                                    316
End (wyrażenie)                                             317
Enum (wyrażenie)                                            319
Environ (funkcja)                                           321
EOF (funkcja)                                               323
Erase (wyrażenie)                                           324
Erl (właściwość)                                            324

                                          Spis treści   |     7
Err (obiekt)                                             325
        Err.Clear (metoda)                                       326
        Err.Description (właściwość)                             327
        Err.GetException (metoda)                                328
        Err.HelpContext (właściwość)                             328
        Err.HelpFile (właściwość)                                329
        Err.LastDLLError (właściwość)                            330
        Err.Number (właściwość)                                  331
        Err.Raise (metoda)                                       331
        Err.Source (właściwość)                                  333
        Error (wyrażenie)                                        333
        ErrorToString (funkcja)                                  334
        Event (wyrażenie)                                        334
        Exception (klasa)                                        336
        Exit (wyrażenie)                                         338
        Exp (funkcja)                                            339
        File (klasa)                                             339
        File.Exists (metoda)                                     340
        FileAttr (funkcja)                                       341
        FileClose (procedura)                                    342
        FileCopy (procedura)                                     343
        FileDateTime (funkcja)                                   343
        FileGet i FileGetObject (procedury)                      344
        FileLen (funkcja)                                        346
        FileOpen (procedura)                                     347
        FilePut i FilePutObject (procedury)                      350
        FileWidth (procedura)                                    351
        Filter (funkcja)                                         352
        Fix (funkcja)                                            353
        Flags (atrybut)                                          354
        Floor (funkcja)                                          354
        FontDialog (klasa)                                       355
        For...Next (wyrażenie)                                   357
        For Each...Next (wyrażenie)                              359
        Format (funkcja)                                         360
        FormatCurrency, FormatNumber i FormatPercent (funkcje)   364
        FormatDateTime (funkcja)                                 365
        FreeFile (funkcja)                                       366
        Friend (słowo kluczowe)                                  367
        Function (wyrażenie)                                     368
        FV (funkcja)                                             372
        GetAllSettings (funkcja)                                 373

8   |    Spis treści
GetAttr (funkcja)                                         374
GetChar (funkcja)                                         375
GetObject (funkcja)                                       376
GetSetting (funkcja)                                      377
GetType (operator)                                        379
Global (słowo kluczowe)                                   379
GoTo (wyrażenie)                                          380
Guid (atrybut)                                            382
Handles (słowo kluczowe)                                  382
Hashtable (klasa)                                         384
Hashtable.Add (metoda)                                    385
Hashtable.ContainsKey (metoda)                            386
Hashtable.ContainsValue (metoda)                          386
Hashtable.CopyTo (metoda)                                 387
Hashtable.Item (właściwość)                               388
Hashtable.Keys (właściwość)                               389
Hashtable.Remove (metoda)                                 389
Hashtable.Values (właściwość)                             390
Hex (funkcja)                                             390
Hour (funkcja)                                            391
IEEERemainder (funkcja)                                   391
If...Then...Else (wyrażenie)                              392
IIf (funkcja)                                             394
Implements (słowo kluczowe)                               395
Implements (wyrażenie)                                    396
Imports (wyrażenie)                                       398
Inherits (wyrażenie)                                      399
Input (procedura)                                         400
InputBox (funkcja)                                        402
InputString (funkcja)                                     403
InStr (funkcja)                                           404
InStrRev (funkcja)                                        405
Int (funkcja)                                             406
Interface...End Interface (wyrażenie)                     407
IPmt (funkcja)                                            410
IRR (funkcja)                                             411
Is (operator)                                             412
IsArray (funkcja)                                         413
IsDate (funkcja)                                          414
IsDBNull (funkcja)                                        415
IsError (funkcja)                                         416
IsNot (operator)                                          417

                                        Spis treści   |     9
IsNothing (funkcja)               418
         IsNumeric (funkcja)               419
         IsReference (funkcja)             419
         Join (funkcja)                    420
         Kill (procedura)                  421
         LBound (funkcja)                  422
         LCase (funkcja)                   423
         Left (funkcja)                    423
         Len (funkcja)                     424
         Like (operator)                   425
         LineInput (funkcja)               426
         Loc (funkcja)                     427
         Lock (procedura)                  428
         LOF (funkcja)                     430
         Log (funkcja)                     430
         Log10 (funkcja)                   432
         LSet (funkcja)                    432
         LTrim (funkcja)                   433
         MarshalAs (atrybut)               434
         Max (funkcja)                     437
         Me (słowo kluczowe)               438
         Mid (funkcja)                     439
         Mid (wyrażenie)                   440
         Min (funkcja)                     441
         Minute (funkcja)                  442
         MIRR (funkcja)                    442
         MkDir (procedura)                 443
         Mod (operator)                    444
         Module...End Module (wyrażenie)   445
         Month (funkcja)                   446
         MonthName (funkcja)               446
         MsgBox (funkcja)                  447
         MTAThread (atrybut)               449
         MyBase (słowo kluczowe)           450
         MyClass (słowo kluczowe)          451
         Namespace (wyrażenie)             453
         New (słowo kluczowe)              453
         Nothing (słowo kluczowe)          454
         Now (właściwość)                  455
         NPer (funkcja)                    455
         NPV (funkcja)                     457
         Obsolete (atrybut)                458

10   |    Spis treści
Oct (funkcja)                                     459
Of (słowo kluczowe)                               459
On Error (wyrażenie)                              460
OpenFileDialog (klasa)                            462
Operator (wyrażenie)                              464
Option Compare (wyrażenie)                        466
Option Explicit (wyrażenie)                       467
Option Strict (wyrażenie)                         468
Out (atrybut)                                     469
ParamArray (atrybut)                              471
Partial (słowo kluczowe)                          471
Partition (funkcja)                               472
PI (pole)                                         474
Pmt (funkcja)                                     475
Pow (funkcja)                                     476
PPmt (funkcja)                                    476
Print i PrintLine (procedury)                     478
Private (słowo kluczowe)                          479
Property (wyrażenie)                              480
Protected (słowo kluczowe)                        484
Public (słowo kluczowe)                           486
PV (funkcja)                                      487
QBColor (funkcja)                                 488
Queue (klasa)                                     489
Queue.Contains (metoda)                           490
Queue.CopyTo (metoda)                             491
Queue.Dequeue (metoda)                            492
Queue.Enqueue (metoda)                            493
Queue.Peek (metoda)                               493
Queue.ToArray (metoda)                            494
RaiseEvent (wyrażenie)                            494
Randomize (procedura)                             496
Rate (funkcja)                                    497
ReDim (wyrażenie)                                 498
Rem (wyrażenie)                                   500
RemoveHandler (wyrażenie)                         501
Rename (procedura)                                502
Replace (funkcja)                                 503
Reset (procedura)                                 504
Resume (wyrażenie)                                505
Return (wyrażenie)                                506
RGB (funkcja)                                     507

                                Spis treści   |    11
Right (funkcja)                         508
         RmDir (procedura)                       509
         Rnd (funkcja)                           510
         Round (funkcja)                         511
         RSet (funkcja)                          512
         RTrim (funkcja)                         513
         SaveFileDialog (klasa)                  514
         SaveSetting (procedura)                 515
         ScriptEngine (właściwość)               517
         ScriptEngineBuildVersion (właściwość)   518
         ScriptEngineMajorVersion (właściwość)   518
         ScriptEngineMinorVersion (właściwość)   519
         Second (funkcja)                        519
         Seek (funkcja)                          520
         Seek (procedura)                        521
         Select Case (wyrażenie)                 522
         Send, SendWait (metody)                 524
         SetAttr (procedura)                     526
         Shadows (słowo kluczowe)                528
         Shared (słowo kluczowe)                 528
         Shell (funkcja)                         529
         Sign (funkcja)                          531
         Sin (funkcja)                           532
         Sinh (funkcja)                          532
         SLN (funkcja)                           533
         Space (funkcja)                         534
         SPC (funkcja)                           534
         Split (funkcja)                         535
         Sqrt (funkcja)                          536
         Stack (klasa)                           537
         Stack.Contains (metoda)                 538
         Stack.CopyTo (metoda)                   539
         Stack.Peek (metoda)                     540
         Stack.Pop (metoda)                      541
         Stack.Push (metoda)                     541
         Stack.ToArray (metoda)                  542
         STAThread (atrybut)                     542
         Static (wyrażenie)                      543
         Stop (wyrażenie)                        543
         Str (funkcja)                           544
         StrComp (funkcja)                       545
         StrConv (funkcja)                       546

12   |    Spis treści
StrDup (funkcja)                                          547
StrReverse (funkcja)                                      548
Structure...End Structure (wyrażenie)                     549
Sub (wyrażenie)                                           551
Switch (funkcja)                                          554
SYD (funkcja)                                             555
SyncLock (wyrażenie)                                      556
SystemTypeName (funkcja)                                  557
TAB (funkcja)                                             557
Tan (funkcja)                                             558
Tanh (funkcja)                                            559
ThreadStatic (atrybut)                                    560
Throw (wyrażenie)                                         561
TimeOfDay (właściwość)                                    562
Timer (właściwość)                                        562
TimeSerial (funkcja)                                      563
TimeString (właściwość)                                   564
TimeValue (funkcja)                                       565
Today (właściwość)                                        566
Trim (funkcja)                                            566
Try...Catch...Finally (wyrażenie)                         567
TryCast (funkcja)                                         569
TypeName (funkcja)                                        570
TypeOf (operator)                                         572
UBound (funkcja)                                          573
UCase (funkcja)                                           573
Unlock (procedura)                                        574
Using...End Using (wyrażenie)                             575
Val (funkcja)                                             577
VarType (funkcja)                                         577
VBFixedArray (atrybut)                                    579
VBFixedString (atrybut)                                   580
VbTypeName (funkcja)                                      581
WebMethod (atrybut)                                       582
WebService (atrybut)                                      583
Weekday (funkcja)                                         584
WeekdayName (funkcja)                                     585
While...End While (wyrażenie)                             586
With...End With (wyrażenie)                               587
WithEvents (słowo kluczowe)                               588
Write i WriteLine (procedury)                             588
Year (funkcja)                                            590

                                        Spis treści   |    13
13. Leksykon przestrzeni nazw My .................................................................................. 591
            AllUsersApplicationData (właściwość)                                                                       592
            AltKeyDown (właściwość)                                                                                    593
            Application (obiekt)                                                                                       594
            ApplicationContext (właściwość)                                                                            595
            AssemblyName (właściwość)                                                                                  596
            Audio (obiekt)                                                                                             597
            AvailablePhysicalMemory (właściwość)                                                                       597
            AvailableVirtualMemory (właściwość)                                                                        598
            ButtonsSwapped (właściwość)                                                                                599
            CapsLock (właściwość)                                                                                      599
            ChangeCulture (metoda)                                                                                     600
            ChangeUICulture (metoda)                                                                                   601
            ClassesRoot (właściwość)                                                                                   602
            Clear (metoda)                                                                                             603
            Clipboard (obiekt)                                                                                         603
            Clock (obiekt)                                                                                             605
            Close (metoda)                                                                                             605
            CombinePath (metoda)                                                                                       606
            CommandLineArgs (właściwość)                                                                               607
            CommentTokens (właściwość)                                                                                 608
            CompanyName (właściwość)                                                                                   609
            Computer (obiekt)                                                                                          610
            ContainsAudio (metoda)                                                                                     611
            ContainsData (metoda)                                                                                      611
            ContainsFileDropList (metoda)                                                                              612
            ContainsImage (metoda)                                                                                     613
            ContainsText (metoda)                                                                                      613
            CopyDirectory (metoda)                                                                                     614
            CopyFile (metoda)                                                                                          616
            Copyright (właściwość)                                                                                     618
            CreateDirectory (metoda)                                                                                   619
            CtrlKeyDown (właściwość)                                                                                   620
            Culture (właściwość)                                                                                       620
            CurrentConfig (właściwość)                                                                                 621
            CurrentDirectory (właściwość)                                                                              622
            CurrentPrincipal (właściwość)                                                                              623
            CurrentUser (właściwość)                                                                                   624
            CurrentUserApplicationData (właściwość)                                                                    625
            DefaultFileLogWriter (właściwość)                                                                          626
            DeleteDirectory (metoda)                                                                                   627
            DeleteFile (metoda)                                                                                        629


14      |    Spis treści
Delimiters (właściwość)                                           630
Deployment (właściwość)                                           632
Description (właściwość)                                          633
Desktop (właściwość)                                              634
DirectoryExists (metoda)                                          634
DirectoryPath (właściwość)                                        635
DoEvents (metoda)                                                 636
DownloadFile (metoda)                                             637
Drives (właściwość)                                               638
DynData (właściwość)                                              639
EndOfData (właściwość)                                            640
ErrorLine (właściwość)                                            641
ErrorLineNumber (właściwość)                                      642
FieldWidths (właściwość)                                          643
FileExists (metoda)                                               644
FileSystem (obiekt)                                               645
FindInFiles (metoda)                                              646
Forms (obiekt)                                                    648
GetAudioStream (metoda)                                           649
GetData (metoda)                                                  650
GetDataObject (metoda)                                            651
GetDirectories (metoda)                                           652
GetDirectoryInfo (metoda)                                         653
GetDriveInfo (metoda)                                             655
GetEnvironmentVariable (metoda)                                   656
GetFileDropList (metoda)                                          657
GetFileInfo (metoda)                                              658
GetFiles (metoda)                                                 660
GetImage (metoda)                                                 661
GetName (metoda)                                                  662
GetParentPath (metoda)                                            663
GetTempFileName (metoda)                                          664
GetText (metoda)                                                  665
GetValue (metoda)                                                 666
GmtTime (właściwość)                                              667
HasFieldsEnclosedInQuotes (właściwość)                            668
Info (obiekt składowy obiektu My.Application)                     669
Info (obiekt składowy obiektu My.Computer)                        670
InitializeWithWindowsUser (metoda)                                670
InstalledUICulture (właściwość)                                   671
IsAuthenticated (właściwość)                                      672
IsAvailable (właściwość)                                          672

                                                Spis treści   |    15
IsInRole (metoda)                                                        673
         IsNetworkDeployed (właściwość)                                           674
         Keyboard (obiekt)                                                        675
         LineNumber (właściwość)                                                  676
         LoadedAssemblies (właściwość)                                            677
         LocalMachine (właściwość)                                                678
         LocalTime (właściwość)                                                   679
         Log (obiekt składowy przestrzeni nazw My)                                680
         Log (obiekt składowy obiektu My.Application)                             680
         MinimumSplashScreenDisplayTime (właściwość)                              681
         Mouse (obiekt)                                                           682
         MoveDirectory (metoda)                                                   683
         MoveFile (metoda)                                                        684
         My (przestrzeń nazw)                                                     686
         MyDocuments (właściwość)                                                 687
         MyMusic (właściwość)                                                     688
         MyPictures (właściwość)                                                  689
         Name (właściwość składowa obiektu My.Computer)                           690
         Name (właściwość składowa obiektu My.User)                               690
         Network (obiekt)                                                         691
         NetworkAvailabilityChanged (zdarzenie składowe obiektu My.Application)   692
         NetworkAvailabilityChanged
         (zdarzenie składowe obiektu My.Computer.Network)                         693
         NumLock (właściwość)                                                     694
         OpenForms (właściwość)                                                   695
         OpenSerialPort (metoda)                                                  696
         OpenTextFieldParser (metoda)                                             698
         OpenTextFileReader (metoda)                                              699
         OpenTextFileWriter (metoda)                                              701
         OSFullName (właściwość)                                                  702
         OSPlatform (właściwość)                                                  703
         OSVersion (właściwość)                                                   704
         PeekChars (metoda)                                                       705
         PerformanceData (właściwość)                                             706
         Ping (metoda)                                                            706
         Play (metoda)                                                            707
         PlaySystemSound (metoda)                                                 709
         Ports (obiekt)                                                           710
         ProductName (właściwość)                                                 711
         ProgramFiles (właściwość)                                                711
         Programs (właściwość)                                                    712
         ReadAllBytes (metoda)                                                    713

16   |    Spis treści
ReadAllText (metoda)                                  714
ReadFields (metoda)                                   715
ReadLine (metoda)                                     716
ReadToEnd (metoda)                                    717
Registry (obiekt)                                     718
RenameDirectory (metoda)                              719
RenameFile (metoda)                                   720
Request (obiekt)                                      721
Resources (obiekt)                                    722
Response (obiekt)                                     723
Run (metoda)                                          724
SaveMySettingsOnExit (właściwość)                     725
Screen (właściwość)                                   726
ScrollLock (właściwość)                               727
SendKeys (metoda)                                     727
SerialPortNames (właściwość)                          730
SetAudio (metoda)                                     731
SetData (metoda)                                      732
SetDataObject (metoda)                                733
SetDelimiters (metoda)                                734
SetFieldWidths (metoda)                               735
SetFileDropList (metoda)                              736
SetImage (metoda)                                     737
SetText (metoda)                                      738
Settings (obiekt)                                     739
SetValue (metoda)                                     741
ShiftKeyDown (właściwość)                             743
Shutdown (zdarzenie)                                  743
SpecialDirectories (obiekt)                           744
SplashScreen (właściwość)                             745
StackTrace (właściwość)                               746
Startup (zdarzenie)                                   748
StartupNextInstance (zdarzenie)                       749
Stop (metoda)                                         750
Temp (właściwość)                                     751
TextFieldParser (obiekt)                              752
TextFieldType (właściwość)                            753
TickCount (właściwość)                                754
Title (właściwość)                                    755
TotalPhysicalMemory (właściwość)                      756
TotalVirtualMemory (właściwość)                       757
TraceSource (właściwość)                              757

                                    Spis treści   |    17
Trademark (właściwość)                                                                              759
          TrimWhiteSpace (właściwość)                                                                         759
          UICulture (właściwość)                                                                              760
          UnhandledException (zdarzenie)                                                                      761
          UploadFile (metoda)                                                                                 762
          User (obiekt)                                                                                       764
          Users (właściwość)                                                                                  765
          Version (właściwość)                                                                                766
          WebServices (obiekt)                                                                                767
          WheelExists (właściwość)                                                                            768
          WheelScrollLines (właściwość)                                                                       769
          WorkingSet (właściwość)                                                                             770
          WriteAllBytes (metoda)                                                                              770
          WriteAllText (metoda)                                                                               771
          WriteEntry (metoda)                                                                                 772
          WriteException (metoda)                                                                             774


 III Dodatki .................................................................................................. 777
     A Elementy języka Visual Basic według kategorii ........................................................ 779
          Obsługa tablic                                                                                      780
          Schowek                                                                                             780
          Obiekty kolekcji                                                                                    781
          Popularne okna dialogowe                                                                            782
          Kompilacja warunkowa                                                                                782
          Konwersja                                                                                           782
          Data i godzina                                                                                      783
          Diagnostyka                                                                                         784
          Deklaracja                                                                                          784
          Obsługa błędów                                                                                      785
          System plików                                                                                       786
          Operacje finansowe                                                                                  787
          Informacja                                                                                          787
          Wejście-wyjście                                                                                     788
          Zintegrowane środowisko programowania                                                               789
          Interakcja                                                                                          789
          Matematyka                                                                                          790
          Struktura programu i przepływ sterowania                                                            791
          Programowanie obiektowe i różne konstrukcje programowe                                              791
          Rejestr                                                                                             793
          Operacje na łańcuchach                                                                              793


18    |    Spis treści
B Hierarchia przestrzeni nazw ......................................................................................795
    Hierarchia przestrzeni nazw My                                                                                               795
    Hierarchia przestrzeni nazw System                                                                                           801

C Stałe i typy wyliczeniowe .......................................................................................... 805
    Stałe wbudowane Visual Basica                                                                                                805
    Klasa ControlChars                                                                                                           808
    Typy wyliczeniowe Visual Basica                                                                                              809

D Co dodano, a co zmieniono w Visual Basicu .NET 2002? .......................................... 815
    Zmiany językowe wprowadzone w Visual Basicu .NET 2002                                                                        815
    Zmiany dotyczące konstrukcji programistycznych                                                                               824
    Przestarzałe konstrukcje programistyczne                                                                                     826
    Ustrukturalizowana obsługa wyjątków                                                                                          827
    Zmiany w technikach programowania obiektowego                                                                                827

E Co dodano, a co zmieniono w Visual Basicu .NET 2003? .......................................... 831
    Zmiany językowe wprowadzone w Visual Basicu .NET 2003                                                                        831

F Co dodano, a co zmieniono w Visual Basicu 2005? ................................................. 833
    Rozszerzenia istniejącej funkcjonalności                                                                                     834
    Przestrzeń nazw My                                                                                                           837
    Pozostałe nowości                                                                                                            838

G Elementy Visual Basica 6, które nie są już obsługiwane ..........................................841

H Kompilator Visual Basica obsługiwany z poziomu wiersza poleceń .......................847
    Podstawy kompilatora Visual Basica                                                                                           847
    Przełączniki wiersza poleceń                                                                                                 848
    Stosowanie pliku odpowiedzi                                                                                                  853
    Stałe kompilacji warunkowej                                                                                                  854

    Skorowidz ....................................................................................................................857




                                                                                                             Spis treści     |    19
ROZDZIAŁ 4.

                                          Zmienne i typy danych



Mechanizmy odpowiedzialne za przetwarzanie danych są sercem wszystkich aplikacji pro-
gramowych. Moglibyśmy oczywiście przetwarzać dane tak jak robi to procesor komputera,
czyli bit po bicie, jednak praca nad odpowiednimi algorytmami szybko by nas znużyła —
właśnie dlatego takie języki jak Visual Basic oferują rozmaite typy danych oraz implementacje
narzędzi zarządzających danymi (z których każdy bazuje na jakimś podzbiorze możliwych
wartości danych). W niniejszym rozdziale zajmiemy się typami danych, sposobami zarzą-
dzania danymi przez te typy oraz technikami ich przetwarzania w języku Visual Basic i plat-
formie .NET.
Pojęcie „typ danych” nie jest tożsame z bardziej ogólnym terminem „typ” wykorzystywanym
w rozmaitych aspektach w tej i innych publikacjach poświęconych technologii .NET. Cała
koncepcja platformy .NET bazuje na pojęciu typu, czyli podstawowej konstrukcji danych
obejmującej klasy, struktury, delegacje i inne wysokopoziomowe elementy wykorzystywane
w procesie konstruowania aplikacji oraz podczas przekazywania danych pomiędzy progra-
mami. Typy danych dostępne w platformie .NET bazują właśnie na tych ogólnie rozumianych
typach (podobnie zresztą jak klasy budowane przez samych programistów). Typy danych
oferują stosunkowo niewielki, ale bardzo istotny zbiór narzędzi przetwarzania danych pogru-
powanych według podzbiorów możliwych wartości (zarządzanych w ramach poszczególnych
typów danych).


Typy danych
Środowisko uruchomieniowe wspólnego języka platformy .NET (CLR) obejmuje między inny-
mi wspólny system typów (CTS), który definiuje typy danych obsługiwane właśnie przez śro-
dowisko CLR. Wszystkie języki programowania przystosowane do współpracy z platformą
.NET muszą implementować przynajmniej podzbiory typów danych środowiska CLR (część
języków implementuje wszystkie, np. Visual Basic począwszy od wydania z 2005 roku).
W technologii .NET typy danych mają postać specjalnych klas i struktur, których egzemplarze
reprezentują wartości danych należące do ograniczonych przedziałów (właściwych dla poszcze-
gólnych typów). Przykładowo, typ danych Byte oferuje możliwość reprezentowania i zarzą-
dzania 8-bitowymi wartościami całkowitoliczbowymi bez znaku, czyli liczbami z przedziału
od 0 do 255. Egzemplarze tego typu nie mogą zawierać wartości spoza tego przedziału (pod-
zbioru), ale przynajmniej z tym konkretnym podzbiorem radzą sobie znakomicie. Platforma
.NET oferuje typy danych dla tych podzbiorów wartości, które są najczęściej wykorzystywane


                                                                                           77
przez programistów podczas wytwarzania aplikacji. Za pomocą tych typów można reprezen-
tować niemal dowolne kombinacje danych. Jeśli predefiniowane typy danych platformy .NET
nie odpowiadają naszym potrzebom, możemy te typy wykorzystać w roli bloków składających
się na naszą własną klasę zarządzającą danymi.
Platforma .NET Framework implementuje blisko dwadzieścia podstawowych typów danych,
z których większość zaprojektowano z myślą o przetwarzaniu liczb całkowitych i zmienno-
przecinkowych. Rdzenne typy danych Visual Basica (znane jeszcze sprzed wprowadzenia plat-
formy .NET) stanowią tylko opakowania dla wspomnianych typów podstawowych systemu
CTS. Przykładowo, stosowany w Visual Basicu typ danych Integer jest opakowaniem struktury
System.Int32. Jedną z wartości struktury Int32 jest stała MaxValue reprezentująca mak-
symalną wartość numeryczną, którą można składować w tym typie danych. Oznacza to, że
choć składowa MaxValue nie jest oficjalną częścią Visual Basica, pełna zależność typu danych
Integer od wspomnianego typu podstawowego Int32 systemu CTS powoduje, że poniższa
para wyrażeń zostanie prawidłowo skompilowana i wykonana:
     Dim usesInt32 As Integer
     MsgBox(usesInt32.MaxValue)           ' Wyświetla 2147483647

Przed wydaniem wersji 2005 tylko niektóre spośród podstawowych typów danych platformy
.NET były implementowane w Visual Basicu. Nawet mimo braku odpowiednich opakowań
Visual Basica, wcześniejsze wydania tego języka (oczywiście już w ramach platformy .NET)
udostępniały „nieopakowane” typy danych systemu CTS. Ponieważ podstawowe typy danych
platformy .NET mają postać klas i struktur, można z nich korzystać w Visual Basicu dokład-
nie tak jak z innych klas czy struktur.


Typy wartościowe i referencyjne
Typy danych w języku Visual Basic można podzielić pomiędzy dwie dość ogólne kategorie:
typy wartościowe (ang. data types) oraz typy referencyjne (ang. reference types). Typy wartościo-
we różnią się od typów referencyjnych przede wszystkim sposobem składowania w pamięci.
Pamięć przydzielana zmiennej typu wartościowego zawiera właściwą wartość tej zmiennej.
Przykładowo, w czasie wykonywania poniższego wyrażenia:
     Dim simpleValue As Integer = 5
zostanie zarezerwowane miejsce w pamięci potrzebne do składowania przypisywanej warto-
ści 5. Inaczej jest w przypadku typów referencyjnych, gdzie pod adresami pamięci przydzielo-
nymi tym zmiennym są składowane adresy innych bloków pamięci, w których znajdują się wła-
ściwe dane. Mechanizm stosowany w typach referencyjnych przypomina trochę usługę
pocztową polegającą na przesyłaniu pod inny adres listów oryginalnie kierowanych do okre-
ślonego odbiorcy. Przykładowo, dla poniższej deklaracji typu referencyjnego:
     Dim somewhereElse As New MyCustomClass

kompilator Visual Basica utworzy w pamięci egzemplarz klasy MyCustomClass, po czym przy-
pisze zmiennej somewhereElse rzeczywisty adres w pamięci tego egzemplarza. Programistom,
którzy mają doświadczenie w pracy ze wskaźnikami oferowanymi przez takie języki jak C++,
zrozumienie mechanizmu stosowanego w Visual Basicu nie powinno sprawić najmniejszych
problemów, ponieważ oba rozwiązania są bardzo podobne.
Najkrócej mówiąc, zmienne typów wartościowych zawierają dane, natomiast zmienne typów
referencyjnych tylko na te dane wskazują.


78    |   Rozdział 4. Zmienne i typy danych
Różnice pomiędzy typami wartościowymi a typami referencyjnymi powodują szereg konse-
kwencji — jedną z najważniejszych jest sposób wykonywania popularnych operacji przypi-
sania. Przeanalizujmy poniższą klasę, która zawiera tylko jedno pole składowe:
   Public Class SimpleClass
      Public Age As Short
   End Class
oraz strukturę będącą odpowiednikiem tej klasy:
   Structure SimpleStruct
      Public Age As Short
   End Structure

W przeciwieństwie do struktur, które są typami wartościowymi, klasy są typami referencyj-
nymi. Poniższy kod ilustruje podstawową różnicę w korzystaniu z tej pary podobnych, ale
mimo wszystko różnych typów:
   ' ----- Deklaruje cztery zmienne, po dwie dla każdego z typów.
   Dim refType1 As SimpleClass
   Dim refType2 As SimpleClass
   Dim valType1 As SimpleStruct
   Dim valType2 As SimpleStruct

   ' ----- W pierwszej kolejności skoncentrujemy się na typach referencyjnych.
   '      Przypisanie refType2 = refType1 spowoduje, że obie zmienne refType2
   '      będą wskazywały na ten sam adres w pamięci. Od tej pory zmiany
   '      składowych zmiennej refType1 będą miały wpływ na składowe zmiennej
   '      refType2 i odwrotnie. Obie zmienne współdzielą ten sam egzemplarz.
   refType1 = New SimpleClass
   refType1.Age = 20
   refType2 = refType1
   refType2.Age = 30
   Debug.WriteLine(refType1.Age) ' --> Wyświetla 30
   Debug.WriteLine(refType2.Age) ' --> Wyświetla 30

   ' ----- Przyjrzyjmy się teraz typom wartościowym. Przypisanie valType2 = valType1
   '      powoduje wykonanie kopii składowych zmiennej valType1. Od tej pory zmiany
   '      składowych jednej z tych zmiennych nie będą miały wpływu na wartości
   '      składowych drugiej zmiennej.
   valType1 = New SimpleStruct
   valType1.Age = 20
   valType2 = valType1
   valType2.Age = 30
   Debug.Writeline(valType1.Age) ' --> Wyświetla 20
   Debug.Writeline(valType2.Age) ' --> Wyświetla 30

W pewnym sensie obie operacje przypisania jednej zmiennej drugiej zmiennej realizują to samo
zadanie — kopiują wartość reprezentowaną przez zmienną użytą po prawej stronie do zmien-
nej na lewo od operatora przypisania. Ponieważ jednak rzeczywistą wartością typu referen-
cyjnego (w tym przypadku zmiennej refType1) jest adres w pamięci, właśnie adres został skopio-
wany do zmiennej refType2. Ponieważ obie zmienne wskazują na ten sam obszar w pamięci
(miejsce przechowywania składowych obiektu klasy SimpleClass), w praktyce zmienne ref-
Type1 i refType2 współdzielą jeden zbiór składowych.

Przypisanie jednej zmiennej typu wartościowego (valType1) innej zmiennej typu wartościowego
(valType2) także polega na skopiowaniu wartości zmiennej użytej na prawo od operatora przy-
pisania do zmiennej użytej z lewej strony tego operatora. Różnica polega na tym, że zmienna
valType1 zawiera rzeczywiste składowe (nie adres miejsca ich przechowywania w pamięci).
Oznacza to, że zmienna docelowa valType2 zawiera odrębną kopię tych składowych (w tym
przypadku jedynej składowej Age).


                                                                                       Typy danych   |   79
Wyzerowanie zmiennej typu referencyjnego wymaga przypisania jej wartości Nothing. Typy
wartościowe zawsze reprezentują jakieś wartości (nawet jeśli są to same zera), zatem w ich
przypadku przypisywanie „wartości” Nothing nie jest możliwe.
Wszystkie podstawowe typy danych Visual Basica, które zarządzają wartościami numerycz-
nymi (czyli np. Integer oraz Double), są typami wartościowymi. Typ danych String jest co
prawda przykładem typu referencyjnego, jednak z perspektywy programisty funkcjonuje
dokładnie tak jak typy wartościowe. Za każdym razem gdy przypisujemy jedną zmienną
łańcuchową innej, wbrew pozorom w łańcuchu docelowym nie jest zapisywana referencja do
pierwszego łańcucha (jak w przypadku innych typów referencyjnych). Wynika to z faktu, że
stosowana w Visual Basicu implementacja typu danych String każdorazowo (zarówno pod-
czas przypisywania, jak i modyfikowania) tworzy zupełnie nowy egzemplarz oryginalnego
łańcucha.


Podstawowe typy danych Visual Basica: przegląd
Język programowania Visual Basic począwszy od wersji 2005 implementuje wszystkie pod-
stawowe typy danych platformy .NET Framework (a konkretnie wspólnego systemu typów,
CTS). Okazuje się, że podstawowe typy danych oferują bardzo szeroki zakres funkcjonalności
i pozwalają zarządzać niemal wszystkimi kategoriami danych. Typy danych należące do sys-
temu CTS można podzielić na pięć grup (według rodzaju zarządzanych danych):
Dane logiczne
   Pojedynczy typ danych, który obejmuje tylko jeden bit reprezentujący prawdę lub fałsz
   (odpowiednio True lub False).
Dane znakowe
   Visual Basic oferuje typy danych zarządzające zarówno pojedynczymi znakami, jak i dłu-
   gimi łańcuchami znaków.
Dane czasu i daty
   Pojedynczy typ danych zarządzający wartościami reprezentującymi zarówno datę, jak
   i godzinę.
Dane zmiennoprzecinkowe
   Rozmaite typy danych reprezentujące wartości zmiennoprzecinkowe — każdy z tych typów
   zarządza ograniczonym podzbiorem liczb wymiernych. Niektóre z tych typów oferują więk-
   szą precyzję matematyczną od pozostałych.
Dane całkowitoliczbowe
   Ta kategoria obejmuje wiele całkowitoliczbowych typów danych, które umożliwiają skła-
   dowanie liczb całkowitych należących do właściwego (zależnego od typu) przedziału (od
   wartości minimalnej do maksymalnej). Część typów danych całkowitoliczbowych obsłu-
   guje wartości ujemne.
W dalszej części tego punktu przedstawimy definicje i stosowne komentarze do każdej z wy-
mienionych powyżej kategorii typów danych obsługiwanych przez Visual Basic.

Typ danych Boolean
Podstawowe fakty
    Podstawowy typ .NET: System.Boolean
    Implementacja: Typ wartościowy (struktura)


80   |   Rozdział 4. Zmienne i typy danych
Ilość zajmowanej pamięci: 2 bajty
    Zakres wartości: True lub False
Typ danych Boolean może reprezentować tylko dwie wartości (True lub False). W języku
Visual Basic mamy do dyspozycji słowa kluczowe True i False, które są stosowane w roli warto-
ści zmiennych typu Boolean. Zmiennym tego typu można też przypisywać wyniki dowol-
nych operacji logicznych.
Kiedy wartość numeryczna jest konwertowana na wartość typu Boolean, wszystkie wartości
różne od zera są przekształcane w wartość True, a jedyną wartością tłumaczoną na False jest
zero. W razie konwersji w drugą stronę wartość False jest zamieniana na zero, natomiast
wartość True jest zamieniana na liczbę –1. (Ta część funkcjonalności odróżnia Visual Basica
od pozostałych języków platformy .NET, które konwertują wartość True na 1. W Visual Basicu
zastosowano w tej roli liczbę –1, aby zapewnić zgodność wstecz. W razie współdzielenia danych
logicznych pomiędzy komponentami napisanymi w różnych językach platformy .NET, środo-
wisko uruchomieniowe .NET Framework i tak automatycznie przekształci te wartości w spo-
sób gwarantujący pełną zgodność).

Typ danych Byte
Podstawowe fakty
    Podstawowy typ .NET: System.Byte
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 1 bajt
    Zakres wartości: Od 0 do 255 (bez znaku)
Typ danych Byte jest najmniejszym dostępnym w Visual Basicu typem całkowitoliczbowym
bez znaku. Mimo bardzo niewielkiego przedziału obsługiwanych wartości zmienne typu Byte
doskonale zdają egzamin podczas pracy z nieprzetworzonymi danymi binarnymi.

Typ danych Char
Podstawowe fakty
    Podstawowy typ .NET: System.Char
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 2 bajty
    Zakres wartości: Kody znaku z przedziału od 0 do 65535 (bez znaku)
Typ danych Char reprezentuje pojedynczy, 16-bitowy znak Unicode. Wszystkie znaki w plat-
formie .NET są reprezentowane właśnie za pomocą kodów 16-bitowych, co oczywiście wy-
starczy do obsługi języków wymagających stosowania 2-bajtowego zbioru znaków (ang. Double-
-Byte Character Set — DBCS), czyli np. języka japońskiego. Wersje Visual Basica sprzed wprowa-
dzenia platformy .NET nie zawierały żadnego odpowiednika typu danych char.
Stosując stałe wartości typu Char, należy do nich dołączać (za cudzysłowem zamykającym)
pojedynczą literę c:
   Dim singleLetter As Char = "A"c




                                                                            Typy danych   |   81
Zmienna łańcuchowa (typu String), która zawiera tylko jeden znak, nie jest tożsama ze
zmienną typu Char zawierającą ten sam znak. Ponieważ są to dwa zupełnie różne typy,
ewentualne przenoszenie danych pomiędzy zmiennymi tych typów wymaga stosownej kon-
wersji (jeśli włączono opcję Option Strict).

Typ danych DateTime
Podstawowe fakty
    Podstawowy typ .NET: System.DateTime
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 8 bajtów
    Zakres wartości: Od 1 stycznia 1 roku n.e. do 31 grudnia 9999 roku n.e. (w kalendarzu
    gregoriańskim)
Wartości reprezentujące daty i czas mają postać 64-bitowych, długich liczb całkowitych zgod-
nych ze standardem IEEE. Za pomocą tak długich liczb można reprezentować daty z prze-
działu od 1 stycznia 1 roku n.e. do 31 grudnia 9999 roku n.e. oraz godziny z przedziału od
0:00:00 do 23:59:59. Odpowiednie wartości reprezentują liczbę „tyknięć”, które upłynęły od 1 sty-
cznia 1 roku n.e. Każde takie „tyknięcie” odpowiada 100 nanosekundom.
Stałe daty należy umieszczać pomiędzy dwoma znakami krzyżyków (#):
     Dim independenceDay As Date = #7/4/1776#


Typ danych Decimal
Podstawowe fakty
Podstawowy typ .NET: System.Decimal
     Implementacja: Typ wartościowy (struktura)
     Ilość zajmowanej pamięci: 12 bajtów
     Zakres wartości: +/–79 228 162 514 264 337 593 543 950 335 bez części dziesiętnej;
     +/–7.9228162514264337593543950335 z 28 miejscami po przecinku; najmniejsza wartość
     różna od zera wynosi +/–0.0000000000000000000000000001
Wartości typu danych Decimal są składowane w formie 96-bitowych liczb całkowitych ze
znakiem; reprezentacja tych wartości dodatkowo obejmuje wewnętrzny (obsługiwany i sto-
sowany w pełni automatycznie) współczynnik skali z przedziału od 0 do 28. Takie rozwią-
zanie zapewnia wysoki poziom precyzji matematycznej w przypadku liczb należących do
odpowiedniego przedziału wartości (typ Decimal szczególnie dobrze sprawdza się w przypadku
danych walutowych).
Na końcu wartości stałych typu Decimal należy umieszczać albo pojedynczą literę D, albo
znak @:
     Dim startingValue As Decimal = 123.45D
     Dim endingValue As Decimal = 543.21@

Znak @ można stosować także do oznaczania deklarowanych zmiennych jako egzemplarzy
typu Decimal:
     Dim startingValue@ = 123.45D




82    |   Rozdział 4. Zmienne i typy danych
Składowe typu danych Decimal nazwane MaxValue i MinValue reprezentują granice obsłu-
giwanego przedziału wartości (odpowiednio wartość maksymalną i minimalną).
W implementacjach Visual Basica sprzed wprowadzenia technologii .NET typ danych Deci-
mal w praktyce nie stanowił odrębnego, autonomicznego typu danych — był podtypem typu
danych Variant. Dopiero w wersjach kwalifikujących Visual Basic do rodziny języków plat-
formy .NET zaimplementowano typ Decimal w formie pełnowartościowego typu danych.

Typ danych Double
Podstawowe fakty
    Podstawowy typ .NET: System.Double
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 8 bajtów
    Zakres wartości: Od –1.79769313486231E+308 do –4.94065645841247E-324 w przypadku
    liczb ujemnych; od 4.94065645841247E–324 do 1.79769313486232E+308 w przypadku
    liczb dodatnich
Wartości typu Double są zgodne ze standardem IEEE dla 64-bitowych (8-bajtowych) liczb
zmiennoprzecinkowych podwójnej precyzji ze znakiem. Mimo ogromnego przedziału obsłu-
giwanych wartości, stosując typ danych Double musimy się liczyć z utratą precyzji w pew-
nych obliczeniach matematycznych.
Stałe egzemplarze typu danych Double należy oznaczać wielką literą R lub znakiem krzyżyka
(#) dołączanym bezpośrednio po wartościach numerycznych:
   Dim startingValue As Double = 123.45R
   Dim endingValue As Double = 543.21#

Znak krzyżyka (#) można stosować także do oznaczania deklarowanych zmiennych jako egzem-
plarzy typu Double:
   Dim startingValue# = 123.45R


Typ danych Int32 (Integer)
Podstawowe fakty
    Podstawowy typ .NET: System.Int32
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 4 bajty
    Zakres wartości: Od –2 147 483 648 do 2 147 483 647
Typ danych Integer umożliwia reprezentowanie 32-bitowych liczb całkowitych ze znakiem.
Właśnie tyle wynosi rdzenna długość słowa w procesorach 32-bitowych, zatem stosowanie
tego rodzaju wartości powinno się przekładać na nieznacznie wyższą wydajność w porówna-
niu z pozostałymi typami całkowitoliczbowymi.
W wersjach Visual Basica sprzed wprowadzenia platformy .NET zmienne i stałe typu Integer
zajmowały tylko 16 bitów i — tym samym — mogły służyć do reprezentowania liczb całko-
witych z dużo mniejszego przedziału. W wersjach języka Visual Basic wchodzących w skład
rodziny języków platformy .NET dodatkowo mamy do dyspozycji typ danych Short, czyli
16-bitowy typ całkowitoliczbowy ze znakiem.



                                                                        Typy danych   |   83
Stałe egzemplarze typu Integer można opcjonalnie oznaczać wielką literą I lub znakiem
procenta (%) dołączanym na końcu wartości numerycznej:
     Dim startingValue As Integer = 123I
     Dim endingValue As Integer = 543%

Znak procenta (%) można stosować także do oznaczania deklarowanych zmiennych jako egzem-
plarzy typu Integer:
     Dim startingValue% = 123I


Typ danych Int64 (Long)
Podstawowe fakty
    Podstawowy typ .NET: System.Int64
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 8 bajtów
    Zakres wartości: Od –9 223 372 036 854 775 808 do 9 223 372 036 854 775 807
Long jest 64-bitowym typem danych całkowitoliczbowych ze znakiem. W wersjach Visual Basica
sprzed wprowadzenia platformy .NET zmienne i stałe typu Long zajmowały tylko 32 bity i tym
samym mogły służyć do reprezentowania liczb całkowitych z dużo mniejszego przedziału.
W wersjach języka Visual Basic wchodzących w skład rodziny języków platformy .NET mamy
do dyspozycji typ danych Integer, czyli 32-bitowy typ całkowitoliczbowy ze znakiem.
Stałe egzemplarze typu Long należy oznaczać wielką literą L lub znakiem & dołączanym na
końcu wartości numerycznej:
     Dim startingValue As Long = 123L
     Dim endingValue As Long = 543&

Znak & można stosować także do oznaczania deklarowanych zmiennych jako egzemplarzy typu
Long:
     Dim startingValue& = 123L

Stosując znak & do oznaczania stałych typu Long, w żadnym razie nie należy pozostawiać
spacji pomiędzy wartością całkowitoliczbową a tym znakiem, ponieważ znak & dodatkowo
pełni w Visual Basicu funkcję operatora konkatenacji łańcuchów.

Typ danych Object
Podstawowe fakty
    Podstawowy typ .NET: System.Object
    Implementacja: Typ referencyjny (klasa)
    Ilość zajmowanej pamięci: 4 bajty
    Zakres wartości: Zmienna typu Object może reprezentować dowolny typ
Object jest uniwersalnym typem danych, co oznacza, że zmienna typu Object może się odwo-
ływać do danych (wskazywać na dane) dowolnego innego typu danych. Przykładowo, egzem-
plarz klasy Object może wskazywać na wartość typu Long, wartość typu String lub egzem-
plarz dowolnej innej klasy.
     Dim amazingVariable As Object
     amazingVariable = 123L
     amazingVariable = "Czyż to nie wspaniałe?"
     amazingVariable = New MyCustomClass


84    |   Rozdział 4. Zmienne i typy danych
Warto pamiętać, że ze stosowaniem zmiennych typu Object wiążą się pewne koszty w wy-
miarze wydajności oprogramowania. Visual Basic nie może związać właściwych składowych
reprezentujących dane ze zmienną typu Object w czasie kompilacji, co oznacza, że odpo-
wiednie łączenie musi nastąpić w czasie wykonywania programu — to z kolei powoduje, że
przetwarzanie metod związanych z tym obiektem wymaga większej ilości kodu. Opisywana
technika bywa nazywana późnym wiązaniem (ang. late binding). Deklarowanie obiektów z wła-
ściwymi (konkretnymi) typami danych skutkuje wczesnym wiązaniem (ang. early binding),
ponieważ za zarządzanie związkami wszystkich składowych odpowiada kompilator. Przy-
kładowo, poniższy fragment kodu:
   Dim lateBound As Object
   . . .
   lateBound = New MyCustomClass
   lateBound.SomeMethod( )
wymusi na aplikacji dopasowanie zmiennej lateBound do składowej SomeMethod klasy MyCu-
stomClass w czasie wykonywania. Przedstawione rozwiązanie jest więc dużo mniej wydajne
od mechanizmu zastosowanego poniżej:
   Dim earlyBound As MyCustomClass
   . . .
   earlyBound = New MyCustomClass
   earlyBound.SomeMethod( )

W wersjach języka Visual Basic sprzed wprowadzenia technologii .NET programista miał do
dyspozycji funkcję VarType, która identyfikowała konkretny podtyp wartości typu Variant.
Okazuje się, że funkcja VarType istnieje także w kolejnych wersjach Visual Basica .NET i służy
do identyfikacji faktycznych typów zmiennych lub wartości. Klasa System.Object (i klasy
potomne, czyli wszystkie klasy w technologii .NET) dodatkowo udostępnia metodę GetType,
która zwraca informację o prawdziwym typie danego obiektu. Chociaż wymienione rozwią-
zania można stosować dla dowolnych typów danych, ich przydatność jest szczególnie widoczna
właśnie w przypadku obiektów typu Object.

Typ danych SByte
Podstawowe fakty
    Podstawowy typ .NET: System.SByte
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 1 bajt
    Zakres wartości: Od —128 do 127
Nowość w wersji 2005. SByte jest najmniejszym typem danych całkowitoliczbowych ze zna-
kiem obsługiwanym przez Visual Basica. Typ SByte jest więc odpowiednikiem opisanego wcze-
śniej typu danych Byte (bez znaku) obejmującym znak.
SByte jest jednym z czterech typów danych dodanych do języka programowania Visual Basic
w wydaniu z roku 2005, które nie są wymienione w minimalnej specyfikacji wspólnego języka
(CLS). W związku z tym, komponenty i aplikacje zbudowane według zaleceń tego minimal-
nego standardu mogą nie być kompatybilne z aplikacjami wykorzystującymi ten typ danych.




                                                                            Typy danych   |   85
Typ danych Int16 (Short)
Podstawowe fakty
    Podstawowy typ .NET: System.Int16
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 2 bajty
    Zakres wartości: Od —32768 do 32767
Short jest 16-bitowym typem danych całkowitoliczbowych ze znakiem. W wersjach języka
Visual Basic sprzed wprowadzenia technologii .NET funkcję 16-bitowego typu całkowitolicz-
bowego ze znakiem pełnił inny typ danych, Integer; typ danych Short w ogóle nie wystę-
pował w tamtych wydaniach Visual Basica.
Stałe egzemplarze typu Short należy oznaczać wielką literą S dołączaną na końcu wartości
numerycznej:
     Dim startingValue As Short = 123S


Typ danych Single
Podstawowe fakty
    Podstawowy typ .NET: System.Single
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 4 bajty
    Zakres wartości: Od –3.402823E+38 do –1.401298E–45 w przypadku liczb ujemnych; od
    1.401298E–45 do 3.402823E+38 w przypadku liczb dodatnich

Wartości typu Single są zgodne ze standardem IEEE dla 32-bitowych (4-bajtowych) liczb
zmiennoprzecinkowych pojedynczej precyzji ze znakiem. Mimo stosunkowo dużego prze-
działu obsługiwanych wartości, stosując typ danych Single, musimy się liczyć z utratą precyzji
w pewnych obliczeniach matematycznych.
Stałe egzemplarze typu danych Single należy oznaczać wielką literą F lub znakiem wykrzyk-
nika (!) dołączanym bezpośrednio po wartościach numerycznych:
     Dim startingValue As Single = 123.45F
     Dim endingValue As Single = 543.21!

Znak wykrzyknika (!) można stosować także do oznaczania deklarowanych zmiennych jako
egzemplarzy typu Single:
     Dim startingValue! = 123.45F


Typ danych String
Podstawowe fakty
    Podstawowy typ .NET: System.String
    Implementacja: Typ referencyjny (klasa)
    Ilość zajmowanej pamięci: 10 + (2 * długość_łańcucha) bajtów
    Zakres wartości: Od zera do około dwóch miliardów znaków Unicode
Typ danych String umożliwia reprezentowanie łańcuchów znakowych zmiennej długości
złożonych maksymalnie z około dwóch miliardów znaków.


86    |   Rozdział 4. Zmienne i typy danych
Wszystkie łańcuchy w technologii .NET są niezmienne (ang. immutable). Oznacza to, że warto-
ści raz przypisanej zmiennej łańcuchowej nie można zmieniać. Kiedy modyfikujemy zawartość
łańcucha, typ danych String zwraca nowy egzemplarz uwzględniający wprowadzone zmiany.
Zmienna String zawierająca pojedynczy znak nie jest tożsama ze zmienną typu Char zawie-
rającą ten sam pojedynczy znak. Ponieważ są to dwa zupełnie różne typy, ewentualne prze-
noszenie danych pomiędzy zmiennymi tych typów wymaga stosownej konwersji (jeśli włą-
czono opcję Option Strict).

Typ danych UInt32 (UInteger)
Podstawowe fakty
    Podstawowy typ .NET: System.Int32
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 4 bajty
    Zakres wartości: Od 0 do 4 294 967 295 (bez znaku)
Nowość w wersji 2005. UInteger jest 32-bitowym typem danych całkowitoliczbowych bez
znaku. Typ UInteger jest więc odpowiednikiem bez znaku opisanego wcześniej typu danych
Integer (ze znakiem).

UInteger jest jednym z czterech typów danych dodanych do języka programowania Visual
Basic w wydaniu z roku 2005, które nie są wymienione w minimalnej specyfikacji wspólnego
języka (CLS). W związku z tym, komponenty i aplikacje zbudowane według zaleceń tego
minimalnego standardu mogą nie być kompatybilne z aplikacjami wykorzystującymi ten typ
danych.

Typ danych UInt64 (ULong)
Podstawowe fakty
    Podstawowy typ .NET: System.Int64
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 8 bajtów
    Zakres wartości: Od 0 do 18 446 744 073 709 551 615 (bez znaku)
Nowość w wersji 2005. ULong jest 64-bitowym typem danych całkowitoliczbowych bez zna-
ku. Typ ULong jest więc odpowiednikiem bez znaku opisanego wcześniej typu danych Long
(ze znakiem).
ULong jest jednym z czterech typów danych dodanych do języka programowania Visual Basic
w wydaniu z roku 2005, które nie są wymienione w minimalnej specyfikacji wspólnego języka
(CLS). W związku z tym, komponenty i aplikacje zbudowane według zaleceń tego minimal-
nego standardu mogą nie być kompatybilne z aplikacjami wykorzystującymi ten typ danych.

Typ danych UInt16 (UShort)
Podstawowe fakty
    Podstawowy typ .NET: System.Int64
    Implementacja: Typ wartościowy (struktura)
    Ilość zajmowanej pamięci: 2 bajty
    Zakres wartości: Od 0 do 65535 (bez znaku)


                                                                         Typy danych   |   87
Nowość w wersji 2005. UShort jest 16-bitowym typem danych całkowitoliczbowych bez znaku.
Typ UShort jest więc odpowiednikiem bez znaku opisanego wcześniej typu danych Short
(ze znakiem).
UShort jest jednym z czterech typów danych dodanych do języka programowania Visual Basic
w wydaniu z roku 2005, które nie są wymienione w minimalnej specyfikacji wspólnego języka
(CLS). W związku z tym, komponenty i aplikacje zbudowane według zaleceń tego minimal-
nego standardu mogą nie być kompatybilne z aplikacjami wykorzystującymi ten typ danych.


Typy danych definiowane przez użytkownika
Chociaż pojedyncze zmienne w zdecydowanej większości przypadków zaspokajają potrzeby
programistów, nierzadko bardziej efektywnym rozwiązaniem jest łączenie wielu podstawowych
wartości danych w ramach logicznych grup. Te niestandardowe typy danych (definiowane
przez użytkownika) rozszerzają zbiór podstawowych typów danych o nowe typy dostosowane
do potrzeb konkretnych programów.
Wersje języka Visual Basic sprzed wprowadzenia technologii .NET oferowały możliwość two-
rzenia typów danych definiowanych przez użytkownika za pośrednictwem wyrażenia Type.
Budowane w ten sposób struktury danych były zwykłymi grupami zmiennych pozbawio-
nymi jakiejkolwiek funkcjonalności (oczywiście poza możliwością ustawiania i odczytywania
wartości reprezentowanych w poszczególnych składowych). W wydaniach Visual Basica
wchodzących w skład platformy .NET Framework znacznie rozszerzono tego rodzaju mechani-
zmy, implementując możliwość definiowania kodu zarówno we wspomnianych strukturach
danych, jak i podstawowych elementach platformy .NET. Typy znane z Visual Basica 6 zastą-
piono konstrukcjami powszechnie stosowanymi w technologii .NET — strukturami (definio-
wanymi ze słowem kluczowym Structure).
Podstawową konstrukcją gromadzącą kod i dane w platformie .NET jest klasa. Klasy pod
wieloma względami przypominają struktury, ale są wolne od pewnych ograniczeń, które
dotyczą wyłącznie struktur. Bodaj najważniejszą różnicą dzielącą struktury od klas jest to, że
w przeciwieństwie do klas (które implementują typy referencyjne), struktury implementują
typy wartościowe (dziedziczące bezpośrednio po typie System.ValueType).
Aby zadeklarować strukturę, należy użyć wyrażenia Structure:
     [Public|Private|Friend] Structure structureName
        deklaracje składowych
     End Structure

Składowymi struktury mogą być pola, właściwości, metody, zdarzenia dzielone, typy wylicze-
niowe oraz inne, zagnieżdżone struktury. Każda ze składowych musi zostać zadeklarowana
z jednym z trzech modyfikatorów dostępu: Public, Private lub Friend.
Najprostszym i najczęściej spotykanym zastosowaniem struktur jest grupowanie wzajemnie
powiązanych zmiennych (nazywanych polami). Przykładowo, w naszym programie możemy
korzystać z prostej struktury definiującej podstawowe informacje o jednej osobie:
     Structure Person
        Public Name As String
        Public Address As String
        Public City As String
        Public State As String
        Public Zip As String
        Public Age As Short
     End Structure


88    |   Rozdział 4. Zmienne i typy danych
Poniżej przedstawiono standardową deklarację definiującą zmienną typu Person:
   Dim onePerson As Person

Dostęp do składowych struktury wymaga użycia standardowej składni „z kropką”, która jest
stosowana także w przypadku składowych klas:
   onePerson.Name = "Beethoven"

Bardziej złożone struktury mogą zawierać zarówno proste pola składowe, jak i właściwości:
   Public Structure NameAndState
      ' ----- Pola publiczne i prywatne.
      Public Name As String
      Private theState As String

      Public Function ShowAll( ) As String
         ' ----- Metoda publiczna. Wyświetla wszystkie składowane wartości.
         If (theState = "") And (Name = "") Then
               Return "<No Name> from <Nowhere>"
         ElseIf (theState = "") Then
               Return Name & " from <Nowhere>"
         ElseIf (Name = "") Then
               Return "<No Name> from " & theState
         Else
               Return Name & " from " & theState
         End If
      End Function

      Public Property State( ) As String
         ' ----- Właściwość publiczna. Ogranicza zbiór wartości reprezentujących stany.
         Get
               Return theState
         End Get
         Set(ByVal value As String)
               If (Len(value) = 2) Then
                   theState = UCase(value)
               Else
                   Throw New System.ArgumentException( _
                       "Stan musi być reprezentowany przez dwa znaki.", "State")
               End If
         End Set
      End Property
   End Structure

Egzemplarze tej struktury mogą być od tej pory tworzone i wykorzystywane dokładnie tak
jak egzemplarze klas:
   Dim onePerson As New NameAndState
   onePerson.Name = "Donna"
   onePerson.State = "CA"
   MsgBox(onePerson.ShowAll())

Struktury mogą być przekazywane na wejściu funkcji w formie argumentów lub wykorzysty-
wane w roli typów zwracanych przez funkcje. Chociaż struktury pod wieloma względami przy-
pominają klasy, nie obsługują szeregu rozwiązań znanych z klas:
 • Struktury nie mogą ani dziedziczyć po innych strukturach, ani same nie mogą być dzie-
   dziczone.
 • Wszystkie konstruktory struktur muszą pobierać parametry wejściowe.
 • Struktury nie mogą definiować destruktorów (metoda Finalize i tak nigdy nie jest wy-
   woływana).


                                                                                    Typy danych   |   89
• Deklaracje składowych nie mogą inicjalizować ich wartości, stosować konstrukcji skład-
      niowej As New ani określać początkowego rozmiaru tablic.
Szczegółowe omówienie terminologii programowania można znaleźć w rozdziale 3.


Konwersja typów danych
Proces konwersji wartości jednego typu na wartość innego typu nazywamy rzutowaniem (ang.
casting) lub po prostu konwersją. Techniki konwersji mogą być stosowane dla wartości sta-
łych, zmiennych lub wyrażeń określonego typu. Język programowania Visual Basic oferuje
szereg funkcji konwertujących, które rzutują wartości jednego typu danych do postaci ich odpo-
wiedników innego typu danych:
      Dim miniSize As Byte = 6
      Dim superSize As Long
      superSize = CLng(miniSize)          ' Konwertuje wartość zmiennej typu Byte na wartość typu Long.
      superSize = CLng("12")              ' Konwertuje stałą typu String na wartość typu Long.

Rzutowania mogą mieć charakter działań rozszerzających lub zawężających. Rzutowanie
rozszerzające (ang. widening cast) ma miejsce wtedy, gdy docelowy typ danych może z powo-
dzeniem reprezentować wszystkie możliwe wartości typu źródłowego (z taką sytuacją mamy
do czynienia np. wtedy, gdy konwertujemy wartość typu Short na wartość typu Integer lub
wartość typu Integer na wartość typu Double). Rzutowanie rozszerzające nigdy nie powoduje
utraty danych. Rzutowanie zawężające (ang. narrowing cast) polega na konwersji oryginal-
nego typu danych na typ, który nie może reprezentować wszystkich możliwych danych typu
źródłowego. Rzutowanie zawężające może prowadzić do utraty części danych lub wręcz błędu
konwersji.
Konwersje typów w Visual Basicu mogą być realizowane na dwa sposoby: jawnie (wprost) lub
w ukryciu. Konwersja niejawna (ang. implicit conversion) jest realizowana przez kompilator,
jeśli okoliczności na to pozwalają (i jeśli samo rzutowanie jest prawidłowe). Przykładowo, jeśli
umieścimy w naszej aplikacji następującą sekwencję wyrażeń:
      Dim smallerData As Integer = 3948
      Dim largerData As Long
      largerData = smallerData
wartość zmiennej smallerData automatycznie zostanie rzutowana do większego typu danych
Long (wykorzystywanego przez zmienną largerData). Ten rodzaj konwersji niejawnej po
części jest uzależniony od ustawienia wyrażenia Option Strict. Wyrażenie Option Strict
powinno się znajdować na samym początku pliku z kodem źródłowym (przed właściwym
kodem klasy):
      Option Strict {On | Off}

Jeśli opcja Option Strict jest włączona (On), kompilator będzie automatycznie wykonywał
tylko rzutowania rozszerzające, co oznacza, że takie rzutowania zawężające jak:
      Dim smallerData As Integer
      Dim largerData As Long = 3948
      smallerData = largerData
spowodują wygenerowanie błędów kompilacji (nawet jeśli faktycznie konwertowane dane mogą
być bez trudu reprezentowane przez typy zmiennych docelowych). Oznacza to, że należy zasto-
sować konwersję jawną (ang. explicit conversion):
      smallerData = CInt(largerData)



90     |   Rozdział 4. Zmienne i typy danych
Ustawiając wartość Off w opcji Option Strict, zezwalamy na stosowanie techniki konwersji
niejawnej nawet wtedy, gdy może to prowadzić do występowania błędów w czasie wykony-
wania programu.
Oprócz wspomnianej opcji Option Strict, Visual Basic oferuje też wyrażenie Option Explicit,
które również powinno być stosowane na początku plików z kodem źródłowym:
   Option Explicit {On | Off}

Kiedy opcja Option Explicit jest włączona (On), wszystkie zmienne muszą być deklarowane
(za pomocą słowa kluczowego Dim lub innego, podobnego) przed użyciem. Kiedy opcja Option
Explicit jest wyłączona (Off), kompilator Visual Basica automatycznie doda (w czasie kompila-
cji) niezbędne deklaracje dla wszystkich nazw napotkanych zmiennych, które nie zostały
wcześniej zadeklarowane. (Nowe wyrażenia Dim nie zostaną umieszczone w naszym kodzie
źródłowym — niezbędne deklaracje zostaną dodane „po cichu” w czasie kompilacji). Wyłą-
czenie tej opcji może prowadzić do występowania w programie trudnych do zlokalizowania
błędów. Więcej informacji na ten temat można znaleźć w podrozdziale „Wyrażenie Option
Explicit” w rozdziale 12. Wartości domyślne obu opcji (Option Strict oraz Option Expli-
cit) można ustawić we właściwościach projektu.

Język Visual Basic zawiera funkcje konwertujące dla wszystkich podstawowych typów danych.
Funkcja CBool
   Konwertuje dowolny prawidłowy łańcuch lub wyrażenie numeryczne na wartość typu
   Boolean. Kiedy wartość numeryczna jest konwertowana na wartość typu Boolean, wszyst-
   kie liczby różne od zera są zamieniane na True i tylko zero jest zamieniane na False.
Funkcja CByte
   Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu-
   giwanego przez typ danych Byte) na wartość typu Byte, zaokrąglając ewentualną część
   ułamkową.
Funkcja CChar
   Konwertuje pierwszy znak łańcucha na wartość typu danych Char.
Funkcja CDate
   Konwertuje dowolną prawidłową reprezentację daty lub godziny na egzemplarz typu Date.
Funkcja CDbl
   Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu-
   giwanego przez typ danych Double) na wartość typu Double.
Funkcja CDec
   Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu-
   giwanego przez typ danych Decimal) na wartość typu Decimal.
Funkcja CInt
   Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu-
   giwanego przez typ danych Integer) na wartość typu Integer, zaokrąglając ewentualną
   część ułamkową.
Funkcja CLng
   Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu-
   giwanego przez typ danych Long) na wartość typu Long, zaokrąglając ewentualną część
   ułamkową.


                                                                           Typy danych   |   91
Funkcja CObj
   Konwertuje dowolne wyrażenie na egzemplarz typu Object. Takie rozwiązanie jest uza-
   sadnione w sytuacji, gdy chcemy, aby typ wartościowy był traktowany jak typ referen-
   cyjny.
Funkcja CSByte
   Nowość w wersji 2005. Konwertuje dowolne wyrażenie numeryczne (którego wartość nale-
   ży do przedziału obsługiwanego przez typ danych SByte) na wartość typu SByte, zaokrą-
   glając ewentualną część ułamkową.
Funkcja CShort
   Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu-
   giwanego przez typ danych Short) na wartość typu Short, zaokrąglając ewentualną część
   ułamkową.
Funkcja CSng
   Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu-
   giwanego przez typ danych Single) na wartość typu Single.
Funkcja CStr
   Konwertuje wyrażenie na jego reprezentację łańcuchową. Przykładowo, wartości typu Boole-
   an mogą być konwertowane na dwa łańcuchy: "True" lub "False". Daty są konwertowane
   na właściwe łańcuchy zgodnie z formatem zdefiniowanym w ramach ustawień regional-
   nych danego komputera.
Funkcja CType
   Oferuje uniwersalny mechanizm rzutowania, za pomocą którego obiekt lub wyrażenie do-
   wolnego typu można przekształcać w odpowiednik innego typu. Funkcja CType może
   być stosowana dla wszystkich klas, struktur i interfejsów. Co więcej, okazuje się, że funkcja
   CType sprawdza się zarówno w przypadku podstawowych typów danych, jak i typów
   (w tym klas) definiowanych przez użytkownika. Poniżej przedstawiono składnię tej funkcji:
         CType(wyrażenie, nazwa-typu)
     Przykładowo, poniższe wyrażenie:
         Dim targetNumber As Integer = CType("12", Integer)
     jest odpowiednikiem następującego wyrażenia:
         Dim targetNumber As Integer = CInt("12")
     Nowość w wersji 2005. W wydaniu Visual Basica z 2005 roku dodano mechanizm przecią-
     żania operatorów, który szczegółowo omówimy w rozdziale 5. Jednym z elementów prze-
     ciążania operatorów jest możliwość definiowania reguł konwersji funkcji CType dla własnych,
     niestandardowych klas.
Funkcja CUInteger
   Nowość w wersji 2005. Konwertuje dowolne wyrażenie numeryczne (którego wartość
   należy do przedziału obsługiwanego przez typ danych UInteger) na wartość typu UInteger,
   zaokrąglając ewentualną część ułamkową.
Funkcja CULong
   Nowość w wersji 2005. Konwertuje dowolne wyrażenie numeryczne (którego wartość
   należy do przedziału obsługiwanego przez typ danych ULong) na wartość typu ULong,
   zaokrąglając ewentualną część ułamkową.


92   |   Rozdział 4. Zmienne i typy danych
Funkcja CUShort
   Nowość w wersji 2005. Konwertuje dowolne wyrażenie numeryczne (którego wartość na-
   leży do przedziału obsługiwanego przez typ danych UShort) na wartość typu UShort,
   zaokrąglając ewentualną część ułamkową.


Zmienne
Zmienną (ang. variable) można zdefiniować jako konstrukcję posiadającą następujące własności:
Nazwę
   Nazwa zmiennej jest wykorzystywana do jej identyfikowania w kodzie źródłowym. W języku
   programowania Visual Basic nazwa zmiennej musi się rozpoczynać albo od litery alfa-
   betu (odpowiedniego znaku Unicode), albo od znaku podkreślenia poprzedzającego kolejny
   znak podkreślenia lub dowolny znak Unicode (literę alfabetu, cyfrę, znak formatujący lub
   kombinację różnych znaków). Wraz z wprowadzeniem technologii .NET firma Microsoft
   zaproponowała nowy zbiór standardów nazewnictwa, które należy stosować w przypadku
   zmiennych i innych nazywanych obiektów. Wspomniane standardy omówiliśmy już w punk-
   cie „Konwencje nazewnicze” w rozdziale 1.
Adres
   Każda zmienna ma przypisany adres pamięciowy, czyli miejsce składowania jej wartości.
   Zmienne stosowane w platformie .NET nie dają nam gwarancji, że reprezentowane dane
   będą stale składowane pod tymi samymi adresami, zatem same adresy zmiennych nie po-
   winny być rejestrowane ani wykorzystywane.
Typ danych
    Typ danych zmiennej określa zakres możliwych wartości, które mogą być przez tę zmien-
    ną reprezentowane.
Wartość
   Wartość zmiennej jest jej właściwą zawartością składowaną pod odpowiednim adresem
   pamięciowym. Wartość zmiennej określa się czasem mianem r-wartości (ang. r-value),
   ponieważ zawsze występuje po prawej stronie operatora przypisania. Przykładowo, poniż-
   sze wyrażenie:
       Dim targetValue As Integer = 5
    można odczytać w następujący sposób: „Zapisz wartość 5 w pamięci, pod adresem repre-
    zentowanym przez zmienną targetValue”. Ponieważ nazwy zmiennej targetValue użyto
    na lewo od operatora przypisania, zmienna (lub jej lokalizacja w pamięci) bywa nazywana
    l-wartością (ang. l-value).
Zakres
    Zakres zmiennej określa miejsca programu, w których dana zmienna będzie widoczna
    z perspektywy kodu źródłowego. Zakres zmiennych omówimy bardziej szczegółowo w dal-
    szej części tego rozdziału.
Czas życia
    Od czasu życia zmiennej zależy to, kiedy i jak długo dana zmienna będzie istniała. Okazuje
    się, że zmienna może, ale nie musi być widoczna (należeć do bieżącego zakresu) w całym
    czasie życia. Także czas życia zmiennych zostanie szczegółowo przeanalizowany w dalszej
    części tego rozdziału.


                                                                               Zmienne   |   93
Deklaracja zmiennej
Deklaracja zmiennej (ang. variable declaration) ma na celu związanie jej nazwy z określonym
typem danych. W przypadku zmiennych nieobiektowych (typów wartościowych) deklaracja
jest równoznaczna z utworzeniem egzemplarza danej zmiennej. Przykładowo, deklaracja
w postaci:
     Dim createMeNow As Integer
tworzy zmienną typu Integer nazwaną createMeNow. Powyższa deklaracja jest równoważna
poniższemu wyrażeniu:
     Dim createMeNow As Integer = New Integer
lub nawet wyrażeniu w postaci:
     Dim createMeNow As New Integer
w którym położono nacisk na sam fakt tworzenia nowego egzemplarza obiektu zmiennej.
Za pomocą pojedynczych wyrażeń można deklarować wiele zmiennych. Ogólnie, mimo że typ
każdej z deklarowanych zmiennych może być inny, każdorazowe stosowanie nazw typów nie
jest bezwzględnie wymagane. Jeśli w deklaracji zmiennej zrezygnujemy z jawnego określenia
typu, wówczas zostanie zastosowany typ kolejnej zmiennej, dla której w sposób bezpośredni
zadeklarowano właściwy typ. Przykładowo, poniższy wiersz kodu:
     Dim first As Long, second, third As Integer, fourth As String
deklaruje między innymi zmienne second i third typu Integer (w Visual Basicu 6 second
byłaby zmienną typu Variant).
Visual Basic oferuje możliwość inicjalizacji zmiennych w wierszach ich deklarowania. (Przy-
pisywana wartość bywa nazywana wartością inicjalizującą — ang. initializer). Przykładowo,
poniższe wyrażenie:
     Dim alwaysInitialized As Integer = 5
deklaruje i tworzy zmienną typu Integer, po czym przypisuje jej wartość początkową równą 5.
Okazuje się, że pojedyncze wyrażenia mogą zawierać także wiele operacji przypisania:
     Dim first As Integer = 6, second As Integer = 9

Warto pamiętać, że w przypadku stosowania wartości inicjalizujących dla każdej ze zmien-
nych należy wprost określić typ danych.
Zmienne obiektowe (zmienne typów referencyjnych) deklarujemy dokładnie tak samo jak ich
odpowiedniki ze świata podstawowych typów danych:
     Dim newHire As Employee

Przedstawiona deklaracja nie tworzy jednak zmiennej obiektowej — po wykonaniu tego wyra-
żenia zmienna newHire będzie miała wartość Nothing. Utworzenie obiektu wymaga jawnego
wywołania konstruktora odpowiedniej klasy na następujące sposoby:
     Dim newHire As New Employee
lub:
     Dim newHire As Employee = New Employee
lub nawet:
     Dim newHire As Employee
     newHire = New Employee




94     |   Rozdział 4. Zmienne i typy danych
Zakres, czas życia i poziom dostępu do zmiennych
Każda zmienna ma swój zakres (ang. scope), który określa, w którym miejscu (lub miejscach)
programu jej identyfikator jest właściwie rozpoznawany — gdzie w kodzie źródłowym dana
zmienna jest widoczna.

Zmienne lokalne: zakresy obejmujące blok kodu lub procedurę
Wszystkie zmienne deklarowane wewnątrz funkcji, procedur bądź właściwości nazywamy
zmiennymi lokalnymi (ang. local variables). Tego rodzaju zmienne mogą być wykorzystywane
wyłącznie w ramach odpowiednich funkcji, procedur i właściwości — kiedy ich wykonywa-
nie się zakończy, wszelkie zmienne lokalne związane z tymi konstrukcjami przestają istnieć
(oczywiście jeśli nie zostały przekazane do innej zmiennej charakteryzującej się szerszym za-
kresem).
Ogólnie, zmienne lokalne charakteryzują się zakresem na poziomie procedury — są dostępne
z poziomu wszystkich wierszy kodu wchodzących w skład odpowiedniej procedury. Dekla-
racje zmiennych lokalnych z reguły występują na samym początku procedur lub funkcji
(w kodzie wykonywanym bezpośrednio po wywołaniu tych konstrukcji):
   Public Sub DoTheWork( )
      Dim localInt As Integer
      Dim localEmp As New Employee

Bloki kodu są zbiorami wyrażeń zawartymi w ramach wyrażeń warunkowych If, w pętlach
For, pętlach With i innych podobnych konstrukcjach języka programowania, dla których sto-
suje się odrębne wyrażenia otwierające i zamykające. Wszystkie wyrażenia zdefiniowane
pomiędzy wyrażeniami otwierającymi (If, ElseIf, For, With itp.) i zamykającymi (End If,
Next, End With itp.) są częścią odpowiednich bloków kodu. Co więcej, zmienna zdefiniowana
wewnątrz bloku kodu charakteryzuje się zakresem na poziomie bloku i jako taka jest widocz-
na tylko w ramach tego bloku. Ponieważ bloki kodu mogą być zagnieżdżane, zmienne lokalne
definiowane na poziomie tych bloków mogą występować dowolnie głęboko w hierarchii tego
rodzaju zagnieżdżeń.
   Public Sub DoTheWork(ByVal fromWhen As Date, ByVal howMuch As Decimal)
       If (fromWhen < Today) Then
     ' ----- Ta zmienna jest dostępna tylko w skrajnie zewnętrznym bloku If,
     '      który dodatkowo zawiera skrajnie wewnętrzny blok If. Zmienna nie
     '      jest dostępna poza skrajnie zewnętrznym blokiem If.
     Dim simpleCalculation As Integer

     If (howMuch > 0@) Then
        ' ----- Ta zmienna jest dostępna tylko w skrajnie wewnętrznym
        '      bloku If.
        Dim complexCalculation As Integer
     End If
     End If
   End Sub

Zmienne dostępne na poziomie bloków w ogóle nie są widoczne spoza bloków, w których
zostały zdefiniowane. Przeanalizujmy teraz następujący blok kodu:
   If (origValue <> 0) Then
         Dim inverseValue As Decimal
         inverseValue = 1 / origValue
   End If
   ' ----- Poniższe wyrażenie zostanie odrzucone przez kompilator.
   MsgBox(CStr(inverseValue))


                                                                               Zmienne   |   95
W powyższym kodzie zmienna inverseValue nie będzie rozpoznawana poza blokiem kodu,
w którym została zdefiniowana, zatem ostatni wiersz przedstawionego kodu spowoduje błąd
kompilacji.
Wszystkie zmienne lokalne, niezależnie od tego, czy deklarujemy ja na poziomie bloków kodu,
czy na poziomie procedur, charakteryzują się czasem życia równym czasowi życia swoich
procedur (lub funkcji). Oznacza to, że zmienne deklarowane na poziomie bloków kodu zacho-
wują swoje wartości przez cały czas życia procedury, która ten blok kodu zawiera (także
w czasie wykonywania kodu spoza tego bloku). Przykładowo, w poniższym kodzie:
     Dim counter As Integer
     For counter = 1 To 5
        If (ProcessData(counter) = True) Then
           Dim soFar1 As Integer
           Dim soFar2 As Integer = 0
           soFar1 += 1
           soFar2 += 1
           MsgBox("Status na tym etapie: " & soFar1 & ", " & soFar2)
        End If
     Next counter
zmienna soFar1 zachowuje swoją wartość z poprzedniego wykonania bloku If, w którym
została zadeklarowana (z poprzedniej iteracji pętli For). W chwili wyświetlania pierwszego
komunikatu wspomniana zmienna będzie zawierała wartość 1, w czasie wyświetlania drugiego
komunikatu będzie zawierała wartość 2 itd. Ponieważ zmienną soFar2 zadeklarowano z warto-
ścią inicjalizującą, wartość tej zmiennej będzie ponownie ustawiana (w tym przypadku zero-
wana) w każdej kolejnej iteracji pętli For. Oznacza to, że wszystkie wyświetlane komunikaty
będą zawierały wartość 1 na drugiej pozycji.
Procedura może wykorzystywać zmienne przekazywane na jej wejściu za pośrednictwem argu-
mentów. Zakres tego rodzaju zmiennych zawsze ogranicza się do poziomu danej procedury.
Czas życia zmiennych lokalnych może wykraczać poza czas wykonywania procedury, w której
te zmienne zadeklarowano. Przykładowo, zmienne statyczne (mimo lokalnego zakresu) „żyją”
przez cały czas istnienia klasy lub modułu, do którego należą. Tego rodzaju zmienne należy
deklarować ze słowem kluczowym Static (zamiast ze standardowym słowem kluczowym Dim):
     Static longLasting As Integer = 0

Wartość inicjalizująca zmiennej statycznej jest stosowana w momencie tworzenia egzempla-
rza odpowiedniej klasy lub modułu (nie każdorazowo w chwili napotkania odpowiedniej
deklaracji). Kiedy wchodzimy do procedury zawierającej jakąś zmienną statyczną, wspomniana
zmienna będzie zawierała dokładnie tę samą wartość, którą zawierała podczas poprzedniego
wykonywania danej procedury. Zmienne statyczne nie mogą być stosowane w procedurach
składowych struktur.

Zakres i poziomy dostępu w ramach modułów
Wszystkie zmienne deklarowane wewnątrz klas (a także struktur i modułów), ale poza jakimi-
kolwiek procedurami składowymi, charakteryzują się zakresem na poziomie typu i jako takie
są dostępne z poziomu wszystkich procedur i funkcji wchodzących w skład tej samej klasy
(lub struktury bądź modułu). Warto jednak pamiętać o możliwości prostego rozszerzania tego
zakresu (poza poziom typu) za pomocą modyfikatorów dostępu (ang. access modifier).




96    |   Rozdział 4. Zmienne i typy danych
Dla każdej zmiennej deklarowanej na poziomie typu należy stosować słowo kluczowe mody-
fikatora dostępu. (Równie dobrze można się posługiwać słowem kluczowym Dim, jednak wów-
czas poziom dostępu będzie uzależniony od typów modułów, co może uczynić nasz kod nieczy-
telnym). Modyfikatory dostępu przydzielają dostęp na poszczególnych poziomach stopniowo —
modyfikator Poblic jest w tym względzie najmniej restrykcyjny (patrz tabela 4.1).

Tabela 4.1. Modyfikatory dostępu

 Modyfikator dostępu   Opis
 Public                Zmienne publiczne są dostępne z poziomu dowolnego kodu, który ma dostęp do egzemplarza klasy
                       bądź struktury lub do typu zawierającego te zmienne. Jeśli jakaś klasa zawiera zmienną publiczną
                       i jeśli egzemplarz tej klasy jest dostępny z poziomu odrębnego projektu, aplikacji lub komponentu, także
                       ta zmienna będzie dostępna z poziomu kodu klienckiego.
 Protected             Zmienne chronione są dostępne zarówno w ramach klasy, w której zostały zadeklarowane,
                       jak i z poziomu wszelkich klas potomnych względem tej klasy (ale nie spoza łańcucha klas związanych
                       relacją dziedziczenia). Zmienne chronione mogą być deklarowane wyłącznie w klasach (nie można
                       ich stosować w strukturach ani modułach).
 Friend                Zmienne zaprzyjaźnione są dostępne z dowolnego miejsca w tym samym podzespole, ale nigdy spoza
                       podzespołu — egzemplarze klasy zawierającej zmienne zaprzyjaźnione ukrywają te zmienne przed kodem
                       zewnętrznym nawet wtedy, gdy same są przez ten kod wykorzystywane. Zmienne zaprzyjaźnione
                       mogą być stosowane w klasach, strukturach i modułach.
 Protected Friend      Stosowanie kombinacji słów kluczowych Protected i Friend powoduje, że tak deklarowane zmienne
                       mają cechy zarówno zmiennych chronionych, jak i zmiennych zaprzyjaźnionych — są dostępne
                       w ramach klasy i klas potomnych oraz w ramach tego samego podzespołu (ale nigdy poza tym
                       podzespołem). Chronione zmienne zaprzyjaźnione mogą być stosowane wyłącznie w klasach (nie można
                       ich stosować w strukturach ani modułach).
 Private               Zmienne prywatne są dostępne z dowolnego punktu tej samej klasy, struktury lub modułu, ale nigdy
                       poza swoją macierzystą konstrukcją. Zmienne prywatne są ukrywane nawet przed składowymi klas
                       potomnych.

Czas życia zmiennych deklarowanych na poziomie typów obejmuje cały czas życia egzem-
plarza klasy, struktury lub modułu, do którego należą. Zmienne można deklarować jako dzielo-
ne (ze słowem kluczowym Shared) i — tym samym — umożliwić istnienie odpowiednich
wartości bez konieczności tworzenia egzemplarza klasy, struktury lub modułu. Warto jednak
pamiętać, że czas życia zmiennych dzielonych rozciąga się na cały okres funkcjonowania aplika-
cji. Wszystkie zmienne deklarowane w ciele modułu domyślnie są składowymi dzielonymi.


Stałe
Stałe (ang. constants) są w istocie zmiennymi dostępnymi tylko do odczytu. Raz ustawionej
w kodzie programu wartości zmiennej (w czasie kompilacji) nie można zmieniać. Stałe są defi-
niowane na poziomie lokalnym lub poziomie modułu za pomocą słowa kluczowego Const:
   modyfikatorDostępu Const nazwa As typ = wartość

gdzie modyfikatorDostępu jest jednym z opisanych w poprzednim podrozdziale modyfika-
torów dostępu. (Modyfikatory dostępu nie są stosowane w przypadku stałych deklarowanych
wewnątrz procedur). Kiedy opcja Option Strinct jest włączona (ma wartość On), wszystkie
stałe muszą być deklarowane z konkretnym typem.




                                                                                                                 Stałe     |      97
Typy wyliczeniowe
Typ wyliczeniowy (ang. enumeration) jest grupą wzajemnie powiązanych stałych całkowito-
liczbowych. Wszystkie składowe wyliczenia muszą być nie tylko egzemplarzami tego samego
typu danych, ale też typu całkowitoliczbowego (Byte, Integer, Long lub Short, a w wersji
2005 lub nowszej również SByte, UInteger, ULong lub UShort). Składowe typu wyliczeniowego
są elementami dzielonymi i dostępnymi tylko do odczytu przez cały czas życia aplikacji.
      Public Enum VehicleType As Integer
         bicycle = 2
         tricycle = 3
         passengerCar = 4
         eighteenWheeler = 18
      End Enum

Składowe typu wyliczeniowego można stosować w kodzie dokładnie tak jak stałe i zmienne:
      Dim whatIDrive As VehicleType
      whatIDrive = VehicleType.passengerCar

Typy wyliczeniowe mogą być deklarowane wyłącznie na poziomie przestrzeni nazw lub modułu
(w żadnym razie nie można ich deklarować wewnątrz procedur).


Tablice
Tablica w wielu językach programowania (włącznie z językiem Visual Basic) jest podstawową
strukturą danych. Tablice umożliwiają składowanie kolekcji egzemplarzy podobnych typów
danych lub obiektów. Każdy element znajduje się na pozycji oznaczonej unikatowym nume-
rem. W Visual Basicu indeksy tablic rozpoczynają się od zera (zero jest dolną granicą) i kończą
na zdefiniowanej górnej granicy.
Poniższe przykłady ilustrują rozmaite sposoby deklarowania tablic jednowymiarowych:
      ' Konstruktor niejawny: Brak rozmiaru początkowego i wartości inicjalizujących.
      Dim days() As Integer

      ' Konstruktor jawny: Brak rozmiaru początkowego i wartości inicjalizujących.
      Dim days() As Integer = New Integer( ) {}

      ' Konstruktor niejawny: Obecność rozmiaru początkowego, brak wartości inicjalizujących.
      Dim days(6) As Integer

      ' Konstruktor jawny: Obecność rozmiaru początkowego, brak wartości inicjalizujących.
      Dim days() As Integer = New Integer(6) {}

      ' Konstruktor niejawny: Rozmiar początkowy wynikający z obecności wartości inicjalizujących.
      Dim days() As Integer = {1, 2, 3, 4, 5, 6, 7}

      ' Konstruktor jawny: Rozmiar początkowy i wartości inicjalizujące.
      Dim days() As Integer = New Integer(6) {1, 2, 3, 4, 5, 6, 7}

Deklaracja tablicy może:
     • wywołać (w sposób jawny lub niejawny) konstruktor tablicy;
     • określić początkowy rozmiar wszystkich wymiarów tablicy lub pozostawić wszystkie roz-
       miary nieokreślone;
     • zainicjalizować elementy tablicy lub pozostawić ich wartości nieokreślone.


98     |    Rozdział 4. Zmienne i typy danych
W Visual Basicu 6 programista mógł określać zarówno dolne, jak i górne granice dla wszystkich
wymiarów tablicy. W języku Visual Basic .NET dolną granicą (najniższym indeksem) wszystkich
tablic jest zero. Przykładowo, wyrażenie w postaci:
   Dim myArray(5) As Integer
deklaruje tablicę złożoną z sześciu elementów, gdzie indeks pierwszego będzie równy 0,
a indeks ostatniego będzie równy 5.
Tablice mogą się składać z wielu wymiarów (ang. dimensions). Przykładowo, poniższy wiersz
deklaruje i inicjalizuje tablicę dwuwymiarową:
   Dim rectArray(,) As Integer = {{1, 2, 3}, {4, 5, 6}}

Poniższy fragment kodu wyświetla zawartość tej tablicy:
   Debug.Write(rectArray(0, 0))
   Debug.Write(rectArray(0, 1))
   Debug.WriteLine(rectArray(0, 2))
   Debug.Write(rectArray(1, 0))
   Debug.Write(rectArray(1, 1))
   Debug.WriteLine(rectArray(1, 2))

   ' ----- Poniżej przedstawiono dane wyjściowe:
   123
   456

Górną granicę każdego z wymiarów tablicy można zmodyfikować za pomocą wyrażenia ReDim,
którego ogólną składnię przedstawiono poniżej:
   ReDim [Preserve] nazwaTablicy(nowaGórnaGranica)

Kwalifikator Preserve powoduje, że wszystkie wartości, które istnieją w momencie wykony-
wania wyrażenia ReDim, zostaną zachowane w tablicy; w razie braku tego kwalifikatora cała
tablica zostanie wyczyszczona. Jeśli zdecydujemy się użyć tego kwalifikatora, powinniśmy
pamiętać, że modyfikacja górnej granicy może dotyczyć tylko ostatniego wymiaru tablicy.
Liczba samych wymiarów tablicy nigdy nie może być zmieniana.
Dolną i górną granicę danego wymiaru tablicy można określić odpowiednio za pomocą funkcji
LBound oraz UBound:
   Dim smallArray(5) As Integer
   MsgBox(UBound(smallArray)) ' Wyświetla liczbę 5.

Ponieważ dolną granicą wszystkich wymiarów tablicy jest indeks zerowy, funkcja LBound
zawsze będzie zwracała właśnie zero.


Kolekcje
Visual Basic oferuje programiście obiekt tablicy asocjacyjnej nazwany kolekcją (ang. collection).
Mimo wielu istotnych podobieństw do standardowych tablic, włącznie z występowaniem
elementów w określonym porządku, warto pamiętać o tym, co odróżnia kolekcję od tablic: jej
elementy mają postać par klucz-wartość. Elementy kolekcji można identyfikować zarówno
według pozycji, jak i według klucza, lub stosując technikę iteracyjnego przeszukiwania kolej-
nych pozycji.
Szczególnie przydatna w codziennej pracy z kolekcjami okazuje się piątka składowych klasy
Collection:



                                                                                  Kolekcje   |   99
Metoda Add
   Dodaje element do kolekcji. Poza samymi danymi można określić opcjonalny klucz, za
   pośrednictwem którego będzie się można odwoływać do nowego elementu.
Metoda Clear
   Usuwa wszystkie elementy z kolekcji.
Właściwość Count
   Zwraca liczbę elementów składowanych w kolekcji.
Właściwość Item
   Zwraca pojedynczy element składowany w kolekcji i identyfikowany albo według indeksu
   (pozycji w ramach kolekcji), albo według klucza (jeśli został określony w chwili dodawa-
   nia tego elementu do kolekcji).
Metoda Remove
   Usuwa z kolekcji element na podstawie przekazanego indeksu bądź klucza.
Poniższy fragment kodu definiuje kolekcję reprezentującą nazwy stanów identyfikowane za
pomocą popularnych skrótów (w tym przypadku skróty występują w roli kluczy):
      Dim states As New Collection
      states.Add("New York", "NY")
      states.Add("Michigan", "MI")

Elementy tej kolekcji można przeszukiwać iteracyjnie za pomocą prostej konstrukcji For
Each...Next:
      Dim oneState As String
      For Each oneState In states
         MsgBox(oneState)
      Next oneState

Podobnie jak w przypadku tablic, dostęp do elementów składowych kolekcji można uzyskiwać
za pośrednictwem odpowiednich wartości indeksu. Dolna granica indeksu kolekcji zawsze
wynosi jeden.
Nowość w wersji 2005. W wersji języka Visual Basic wydanej w roku 2005 wprowadzono typy
uniwersalne, które umożliwiają wiązanie egzemplarzy kolekcji (i innych klas) z konkretnymi
typami danych w czasie wykonywania programu. Więcej informacji na ten temat można
znaleźć w rozdziale 10.


Parametry i argumenty
Chociaż procedury są autonomicznymi blokami kodu, ich prawidłowe funkcjonowanie czę-
sto wymaga interakcji z danymi spoza samych procedur. Dane zewnętrzne można przeka-
zywać do procedur za pośrednictwem tzw. listy parametrów. Listę parametrów definiujemy
w wierszu deklaracji procedury (w nawiasie, bezpośrednio za nazwą samej procedury):
      Public Function RepeatString(ByVal origText As String, _
               ByVal howManyTimes As Integer) As String
         ' ----- Zwraca łańcuch wielokrotnie skonkatenowany z samym sobą.
         Dim counter As Integer
         RepeatString = ""
         For counter = 1 To howManyTimes
               RepeatString &= origText
         Next counter
      End Function



100    |   Rozdział 4. Zmienne i typy danych
Funkcja RepeatString otrzymuje na wejściu dwa parametry: origText oraz howManyTimes. Dla
każdego parametru określono zarówno typ danych, jak i metodę przekazywania. Metoda przeka-
zywania parametru to albo ByVal (przez wartość), albo ByRef (przez referencję). W technologii
.NET domyślnym sposobem przekazywania parametrów jest przekazywanie przez wartość.
Podczas wywoływania procedury pobierającej parametry przekazujemy na jej wejściu warto-
ści, które na poziomie kodu wywołującego z reguły nazywa się argumentami. Przykładowo,
poniższe wyrażenie dołącza dwa argumenty do wywołania funkcji RepeatString: łańcuch
"abc" oraz liczbę całkowitą 5:
   targetString = RepeatString("abc", 5)

Ponieważ w technologii .NET klasy mogą zawierać metody przeciążone, argumenty przekazy-
wane przez nas na wejściu procedury muszą odpowiadać sygnaturze dokładnie jednej z prze-
ciążonych wersji wywoływanej metody. Bardziej szczegółowe omówienie techniki przeciąża-
nia można znaleźć w rozdziale 3.


Przekazywanie argumentów
Wszystkie argumenty są przekazywane albo przez wartość, albo przez referencję (w zależności
od tego, czy przed nazwą odpowiedniego parametru użyjemy słowa kluczowego ByVal, czy
ByRef). Kiedy dane są przekazywane przez wartość, docelowa procedura otrzymuje kopię
wyrażenia lub zmiennej źródłowej. W samej procedurze parametr jest traktowany dokładnie
tak jak zmienna lokalna — może być dowolnie wykorzystywany i modyfikowany, ale prze-
staje istnieć w chwili zakończenia wykonywania procedury. Żadna ze zmian wartości parame-
trów przekazanych przez wartość (zadeklarowanych ze słowem kluczowym ByVal) w ramach
procedury nie będzie miała wpływu na wartość zmiennej źródłowej. Opisana zasada jest szcze-
gólnie łatwa do weryfikacji w przypadku typów wartościowych. Przykładowo, przeanalizujmy
teraz następujący fragment kodu:
   Public Sub ParentRoutine()
      Dim sourceValue As Integer = 5
      ChildRoutine(sourceValue)
      MsgBox(sourceValue)   ' --> Wyświetla 5
   End Sub

   Public Sub ChildRoutine(ByVal incoming As Integer)
      incoming = 10
   End Sub

Chociaż wartość zmiennej sourceValue przekazanej do procedury ChildRoutine (za pośred-
nictwem parametru incoming) została przez tę procedurę zmodyfikowana, odpowiednia zmiana
nie została propagowana do kodu procedury wywołującej ParentRoutine, ponieważ para-
metr incoming reprezentował kopię wartości zmiennej sourceValue.
Z drugiej strony, obiekty (egzemplarze typów referencyjnych) przekazywane do procedur przez
wartość mogą być przez te procedury modyfikowane. Precyzyjnie mówiąc, na poziomie pro-
cedury można modyfikować składowe przekazanego obiektu, nie sam obiekt. W przypadku
obiektów przekazywanych przez wartość w praktyce następuje przekazanie adresu pamięcio-
wego, stąd zmiany dokonywane przez procedurę na danym obszarze pamięci znajdują odzwier-
ciedlenie w oryginalnym obiekcie. Warto jednak pamiętać, że obiektu przekazanego przez
wartość nie można na poziomie procedury zastąpić innym egzemplarzem tej samej klasy (nasze
możliwości obejmują wyłącznie modyfikowanie składowych):


                                                                   Parametry i argumenty   |   101
Public Class DataClass
         Public DataMember As Integer
      End Class

      Public Class CodeClass
         Public Sub ParentRoutine()
            Dim sourceValue As New DataClass
            sourceValue.DataMember = 5
            ChildRoutine(sourceValue)
            MsgBox(sourceValue.DataMember)   ' --> Wyświetla 10
         End Sub

           Public Sub ChildRoutine(ByVal incoming As DataClass)
              ' ----- Poniższy wiersz zmienia „rzeczywistą” składową.
              incoming.DataMember = 10

            ' ----- Poniższe wiersze nie mają wpływu na zmienną sourceValue.
            incoming = New DataClass
            incoming.DataMember = 15
         End Sub
      End Class

Przekazywanie przez referencję (za pośrednictwem parametru zadeklarowanego ze słowem
kluczowym ByRef) argumentu typu wartościowego na wejściu procedury zawsze oznacza
przekazanie adresu pamięciowego odpowiedniej wartości — oznacza to, że ewentualne
zmiany wprowadzone przez procedurę docelową będą miały bezpośredni wpływ na wartość
odpowiedniej zmiennej źródłowej. (Ten mechanizm jest stosowany pod warunkiem, że wartość
źródłowa jest składowana w zmiennej; stałe i wyrażenia obliczane w samym wywołaniu
z natury rzeczy nie mogą być modyfikowane). Przykładowo, spróbujmy porównać poniższy
kod ze słowem kluczowym ByRef z przedstawionym przed momentem odpowiednikiem zawie-
rającym parametr przekazywany przez wartość:
      Public Sub ParentRoutine()
         Dim sourceValue As Integer = 5
         ChildRoutine(sourceValue)
         MsgBox(sourceValue)   ' --> Wyświetla 10
      End Sub

      Public Sub ChildRoutine(ByRef incoming As Integer)
         incoming = 10
      End Sub

Jak widać, zastąpienie słowa kluczowego ByVal słowem ByRef miało istotny wpływ na funk-
cjonowanie tego fragmentu kodu. W przypadku typów referencyjnych różnica nie jest tak
widoczna, chyba że spróbujemy w procedurze docelowej całkowicie zastąpić oryginalny
obiekt. Przekazywanie przez referencję daje taką możliwość! Wynika to z faktu, że słowo klu-
czowe ByRef wymusza przekazywanie do procedury adresu adresu pamięciowego. Modyfi-
kując ten adres pamięciowy, możemy w prosty sposób zastąpić adres reprezentowany przez
zmienną źródłową. W niektórych językach programowania opisywany schemat jest nazywany
podwójnym wskaźnikiem (ang. double pointer). Wszelkie wątpliwości związane z tym mecha-
nizmem powinien wyjaśnić poniższy przykład. Warto porównać ten fragment kodu z podob-
nym fragmentem, w którym zastosowano słowo kluczowe ByVal:
      Public Class DataClass
         Public DataMember As Integer
      End Class

      Public Class CodeClass
         Public Sub ParentRoutine(              )



102    |    Rozdział 4. Zmienne i typy danych
Dim sourceValue As New DataClass
          sourceValue.DataMember = 5
          ChildRoutine(sourceValue)
          MsgBox(sourceValue.DataMember)   ' --> Wyświetla 15
       End Sub

       Public Sub ChildRoutine(ByRef incoming As DataClass)
          ' ----- Poniższy wiersz zmienia „rzeczywistą” składową.
          incoming.DataMember = 10

         ' ----- Poniższe wiersze całkowicie zastępują egzemplarz wskazywany
         '      przez zmienną obiektową sourceValue.
         incoming = New DataClass
         incoming.DataMember = 15
      End Sub
   End Class

Stosowanie parametrów przekazywanych przez referencję łącznie z referencyjnymi typami
danych umożliwia procedurom docelowym zastępowanie oryginalnych obiektów zupełnie
nowymi egzemplarzami właściwych klas.


Argumenty opcjonalne
Język Visual Basic obsługuje parametry opcjonalne za pośrednictwem słowa kluczowego
Optional:
   Sub Calculate(Optional ByVal silent As Boolean = False)

W przypadku wszystkich parametrów opcjonalnych ma zastosowanie następująca para reguł:
 • Każda deklaracja argumentu opcjonalnego musi obejmować wartość domyślną, która do-
   datkowo musi mieć postać wyrażenia stałego (w żadnym razie nie może być zmienną).
   Wartość domyślna jest wykorzystywana tylko wtedy, gdy kod wywołujący nie dostarcza
   argumentu dla parametru opcjonalnego.
 • Każdy parametr zadeklarowany po parametrze opcjonalnym także musi być opcjonalny.
   Oznacza to, że ewentualne parametry obowiązkowe (nieopcjonalne) muszą się znajdo-
   wać na liście parametrów przed parametrami opcjonalnymi.
W wersjach Visual Basica sprzed wprowadzenia technologii .NET istniała możliwość rezygnacji
z wartości domyślnej i — jeśli typem parametru był Variant — stosowania funkcji IsMissing do
określania, czy odpowiednia wartość została przekazana. Opisane rozwiązanie nie jest obsłu-
giwane w platformie .NET, zatem dla wszystkich parametrów opcjonalnych koniecznie mu-
simy definiować wartości domyślne (na wypadek braku odpowiednich argumentów).


Tablice parametrów
W normalnych warunkach definicja procedury określa stałą liczbę parametrów. Programiści
Visual Basica mają jednak do dyspozycji słowo kluczowe ParamArray (od ang. parameter array —
tablica parametrów), za pośrednictwem którego można rozszerzać listę parametrów poza stały
zbiór elementów. Każde wywołanie tak zdefiniowanej procedury może zawierać inną liczbę
parametrów (oczywiście oprócz puli parametrów wymaganych).
Przeanalizujmy przykład funkcji wyznaczającej średnią ocenę z egzaminów, których liczba
nie jest znana (liczba ocen wejściowych w każdym wywołaniu może być inna):



                                                                               Parametry i argumenty   |   103
Public Function AverageScore(ByVal ParamArray scores(             ) _
               As Single) As Single
         ' ----- Oblicza średnią ocenę dla dowolnej liczby egzaminów.
         Dim counter As Integer

         AverageScore = 0
         For counter = 0 To UBound(scores)
            AverageScore += scores(counter)
         Next counter
         AverageScore /= UBound(scores) + 1
      End Function

Wywołania funkcji AverageScore mogą teraz zawierać zróżnicowaną liczbę argumentów:
      MsgBox(AverageScore(1, 2, 3, 4, 5))        ' --> Wyświetla 3
      MsgBox(AverageScore(1, 2, 3))              ' --> Wyświetla 2

Poniżej przedstawiono reguły, które mają zastosowanie w przypadku parametrów deklarowa-
nych ze słowem kluczowym ParamArray:
  • Procedura może otrzymywać na wejściu tylko jedną tablicę parametrów i ta tablica musi
      być ostatnim elementem na liście parametrów.
  • Tablica parametrów musi być przekazywana przez wartość, a jej deklaracja na liście para-
      metrów procedury zawsze musi być opatrywana słowem kluczowym ByVal.
  • Tablica parametrów musi być strukturą jednowymiarową. Jeśli nie zadeklarujemy jej typu,
      kompilator automatycznie założy, że tablica składa się z elementów typu System.Object.
Tablica parametrów zawsze jest parametrem opcjonalnym. Jej domyślną wartością jest pusta
tablica jednowymiarowa właściwego typu danych.




104    |   Rozdział 4. Zmienne i typy danych

More Related Content

PDF
PHP5. Obiekty, wzorce, narzędzia
PDF
J2EE. Wzorce projektowe
PDF
Linux dla programistów i użytkowników
PDF
Montaż komputera PC. Ilustrowany przewodnik
PDF
AJAX w mgnieniu oka
PDF
Magia w działaniu. Sesje NLP Richarda Bandlera
PDF
Ajax. Zaawansowane programowanie
PDF
Fotografia cyfrowa. Kurs. Wydanie II
PHP5. Obiekty, wzorce, narzędzia
J2EE. Wzorce projektowe
Linux dla programistów i użytkowników
Montaż komputera PC. Ilustrowany przewodnik
AJAX w mgnieniu oka
Magia w działaniu. Sesje NLP Richarda Bandlera
Ajax. Zaawansowane programowanie
Fotografia cyfrowa. Kurs. Wydanie II

Viewers also liked (9)

PDF
JavaScript dla każdego. Wydanie IV
PDF
Praktyczny kurs Java. Wydanie II
PDF
Tworzenie stron WWW. Ilustrowany przewodnik
PDF
PHP5. Bezpieczne programowanie. Leksykon kieszonkowy
PDF
Sekrety RSS
PDF
SQL Server 2005
PDF
ASP.NET 2.0. Księga eksperta
PDF
Internet. Kurs. Wydanie II
PDF
CMS. Jak szybko i łatwo stworzyć stronę WWW i zarządzać nią
JavaScript dla każdego. Wydanie IV
Praktyczny kurs Java. Wydanie II
Tworzenie stron WWW. Ilustrowany przewodnik
PHP5. Bezpieczne programowanie. Leksykon kieszonkowy
Sekrety RSS
SQL Server 2005
ASP.NET 2.0. Księga eksperta
Internet. Kurs. Wydanie II
CMS. Jak szybko i łatwo stworzyć stronę WWW i zarządzać nią
Ad

Similar to Visual Basic 2005. Almanach (20)

PDF
Visual Basic 2005. Od podstaw
PDF
Visual Basic .NET. Ćwiczenia
PDF
Visual Basic .NET. Encyklopedia
PDF
Visual Basic 2005. Wprowadzenie do programowania w .NET
PDF
Visual Basic 2005. Zapiski programisty
PDF
Visual Basic 2005. Programowanie
PDF
C#. Ćwiczenia. Wydanie II
PDF
C#. Programowanie
PDF
Zrozumieć platformę .NET. Wydanie II
PDF
Programowanie obiektowe w Visual Basic .NET dla każdego
PDF
Delphi. Szybki start
PDF
C# 2005. Wprowadzenie
PDF
Microsoft Visual Basic .NET 2003. Księga eksperta
PDF
Visual Basic .NET. Księga eksperta
PDF
Aplikacje w Visual C++ 2005. Przykłady
PDF
Delphi 2006. Ćwiczenia praktyczne
PDF
C#. Ćwiczenia
PDF
Visual Basic 2008. Warsztat programisty
PDF
Delphi 7 dla każdego
PDF
Visual C# 2005. Zapiski programisty
Visual Basic 2005. Od podstaw
Visual Basic .NET. Ćwiczenia
Visual Basic .NET. Encyklopedia
Visual Basic 2005. Wprowadzenie do programowania w .NET
Visual Basic 2005. Zapiski programisty
Visual Basic 2005. Programowanie
C#. Ćwiczenia. Wydanie II
C#. Programowanie
Zrozumieć platformę .NET. Wydanie II
Programowanie obiektowe w Visual Basic .NET dla każdego
Delphi. Szybki start
C# 2005. Wprowadzenie
Microsoft Visual Basic .NET 2003. Księga eksperta
Visual Basic .NET. Księga eksperta
Aplikacje w Visual C++ 2005. Przykłady
Delphi 2006. Ćwiczenia praktyczne
C#. Ćwiczenia
Visual Basic 2008. Warsztat programisty
Delphi 7 dla każdego
Visual C# 2005. Zapiski programisty
Ad

More from Wydawnictwo Helion (20)

PDF
Tworzenie filmów w Windows XP. Projekty
PDF
Blog, więcej niż internetowy pamiętnik
PDF
Access w biurze i nie tylko
PDF
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
PDF
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
PDF
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
PDF
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
PDF
Makrofotografia. Magia szczegółu
PDF
Windows PowerShell. Podstawy
PDF
Java. Efektywne programowanie. Wydanie II
PDF
JavaScript. Pierwsze starcie
PDF
Ajax, JavaScript i PHP. Intensywny trening
PDF
PowerPoint 2007 PL. Seria praktyk
PDF
Excel 2007 PL. Seria praktyk
PDF
Access 2007 PL. Seria praktyk
PDF
Word 2007 PL. Seria praktyk
PDF
Serwisy społecznościowe. Budowa, administracja i moderacja
PDF
AutoCAD 2008 i 2008 PL
PDF
Bazy danych. Pierwsze starcie
PDF
Inventor. Pierwsze kroki
Tworzenie filmów w Windows XP. Projekty
Blog, więcej niż internetowy pamiętnik
Access w biurze i nie tylko
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Makrofotografia. Magia szczegółu
Windows PowerShell. Podstawy
Java. Efektywne programowanie. Wydanie II
JavaScript. Pierwsze starcie
Ajax, JavaScript i PHP. Intensywny trening
PowerPoint 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
Serwisy społecznościowe. Budowa, administracja i moderacja
AutoCAD 2008 i 2008 PL
Bazy danych. Pierwsze starcie
Inventor. Pierwsze kroki

Visual Basic 2005. Almanach

  • 1. Visual Basic 2005. Almanach Tim Patrick, Steven Roman, Ron Petrusha, Paul Lomax T³umaczenie: Miko³aj Szczepaniak ISBN: 83-246-0475-8 Tytu³ orygina³u: Visual Basic 2005 in a Nutshell Format: B5, stron: 880 Przyk³ady na ftp: 7 kB Visual Basic po raz pierwszy pojawi³ siê na rynku w roku 1991 jako po³¹czenie oferowanego przez Microsoft jêzyka QBasic z mechanizmem projektowania graficznego interfejsu u¿ytkownika. Od tej pory przeszed³ spor¹ ewolucjê, zyskuj¹c jednoczeœnie ogromne grono zwolenników. W roku 2001 wprowadzono na rynek platformê programistyczn¹ .NET wraz z ca³kowicie zmienion¹ i odnowion¹ wersj¹ Visual Basica pod nazw¹ Visual Basic .NET. Visual Basic dla platformy .NET by³ jêzykiem w pe³ni obiektowym i oferowa³ znacznie wiêksze mo¿liwoœci ni¿ jego poprzednicy. Visual Basic 2005 to najnowsze wcielenie tego popularnego jêzyka programowania. Ksi¹¿ka „Visual Basic 2005. Almanach” to kompleksowe omówienie wszystkich zagadnieñ zwi¹zanych z programowaniem w tym jêzyku. Czytaj¹c j¹, poznasz genezê platformy .NET, jej sk³adniki i konstrukcjê oraz s³owa kluczowe jêzyka Visual Basic. Przeczytasz o programowaniu obiektowym, klasach platformy .NET, obs³udze zdarzeñ oraz typach uniwersalnych. Dalsza czêœæ ksi¹¿ki to niezwykle przydatne ka¿demu programiœcie zestawienie dokumentacji wszystkich istotnych wyra¿eñ, procedur, funkcji i obiektów Visual Basica zawieraj¹ce omówienie sk³adni i argumentów, wskazówki dotycz¹ce sposobu stosowania omawianego elementu jêzyka, przyk³ady kodu oraz opisy nieudokumentowanych zachowañ. W ksi¹¿ce omówiono: • Podstawowe wiadomoœci o platformie .NET • Zasady programowania obiektowego • Zmienne, typy danych i operatory • Struktura programów w Visual Basic • Klasy platformy .NET • Typy uniwersalne Wydawnictwo Helion • Obs³uga b³êdów i wyj¹tków ul. Koœciuszki 1c • Leksykon elementów jêzyka Visual Basic 2005 44-100 Gliwice Zostañ ekspertem w dziedzinie programowania w Visual Basicu tel. 032 230 98 63 e-mail: helion@helion.pl
  • 2. Spis treści Przedmowa ................................................................................................................... 21 I Podstawy .................................................................................................29 1. Wprowadzenie .............................................................................................................. 31 Dlaczego Visual Basic .NET? 32 Czym jest Visual Basic .NET? 36 Co możemy zrobić w środowisku Visual Basic .NET? 42 Wersje języka Visual Basic .NET 43 2. Platforma .NET Framework: pojęcia ogólne ................................................................45 Środowisko uruchomieniowe wspólnego języka 45 Kod zarządzany 46 Przestrzenie nazw 47 Typy i obiekty 48 Podzespoły 49 Biblioteka klas platformy .NET (FCL) 51 Wdrażanie aplikacji 52 Platforma .NET i język Visual Basic 52 3. Wprowadzenie do programowania obiektowego .....................................................53 Reguły programowania obiektowego 53 Programowanie obiektowe w języku Visual Basic 58 4. Zmienne i typy danych .................................................................................................. 77 Typy danych 77 Zmienne 93 Stałe 97 Typy wyliczeniowe 98 Tablice 98 Kolekcje 99 Parametry i argumenty 100 3
  • 3. 5. Operatory .................................................................................................................... 105 Operatory arytmetyczne 105 Operatory konkatenacji 107 Operatory logiczne i bitowe 107 Operatory przypisania 112 Operatory porównania 114 Operatory obiektowe 115 Przeciążanie operatorów 117 Priorytety operatorów 119 6. Struktura programu .....................................................................................................121 Rodzaje aplikacji tworzonych w środowisku Visual Studio 121 Techniki odwołań do komponentów i klas 122 Punkty wejścia aplikacji 123 Zawartość pliku z kodem źródłowym 126 Struktura programu Visual Basica 127 7. Biblioteka klas platformy .NET ................................................................................... 135 Przestrzeń nazw System 136 Przestrzeń nazw System.Collections 142 Przestrzeń nazw System.Data 142 Przestrzeń nazw System.IO 143 Przestrzeń nazw System.Text.RegularExpressions 144 Przestrzeń nazw System.Windows.Forms 146 Pozostałe przestrzenie nazw 146 8. Delegacje i zdarzenia .................................................................................................. 149 Delegacje 150 Zdarzenia i wiązanie zdarzeń 153 9. Atrybuty ...................................................................................................................... 159 Składnia i techniki stosowania 160 Definiowanie atrybutów niestandardowych 163 Korzystanie z atrybutów niestandardowych 166 10. Typy uniwersalne .........................................................................................................171 Czym są typy uniwersalne? 171 Parametry typów 172 Stosowanie wielu parametrów typów 173 Ograniczenia 173 Ograniczenia złożone 174 Uzyskiwanie dostępu do składowych parametrów typów 175 4 | Spis treści
  • 4. Metody uniwersalne 177 Zagnieżdżone typy uniwersalne 177 Typy i składowe przeciążone 177 11. Obsługa błędów w Visual Basicu ............................................................................... 179 Wykrywanie i obsługa błędów 179 Obsługa błędów wykonywania 180 Obsługa błędów logiki 188 Stałe błędów 191 II Leksykon ................................................................................................ 193 12. Leksykon języka Visual Basic ...................................................................................... 195 #Const (dyrektywa) 197 #If...Then...#Else (dyrektywa) 198 #Region...#End Region (dyrektywa) 200 Abs (funkcja) 200 Acos (funkcja) 201 AddHandler (wyrażenie) 202 AddressOf (operator) 203 AppActivate (procedura) 203 Application (klasa) 205 Application.CompanyName (właściwość) 206 Application.DoEvents (metoda) 207 Application.ExecutablePath (właściwość) 208 Application.ProductName (właściwość) 209 Application.ProductVersion (właściwość) 209 Application.Run (metoda) 210 Array (klasa) 211 Array.BinarySearch (metoda) 212 Array.Copy (metoda) 214 Array.IndexOf (metoda) 215 Array.LastIndexOf (metoda) 216 Array.Reverse (metoda) 217 Array.Sort (metoda) 218 Asc i AscW (funkcje) 220 AssemblyVersion (atrybut) 220 Asin (funkcja) 221 Atan (funkcja) 222 Atan2 (funkcja) 223 AttributeUsage (atrybut) 224 Beep (procedura) 225 Spis treści | 5
  • 5. Call (wyrażenie) 225 CallByName (funkcja) 226 CBool (funkcja) 228 CByte (funkcja) 228 CChar (funkcja) 229 CDate (funkcja) 230 CDbl (funkcja) 231 CDec (funkcja) 231 Ceiling (funkcja) 232 ChDir (procedura) 233 ChDrive (procedura) 234 Choose (funkcja) 235 Chr i ChrW (funkcje) 237 CInt (funkcja) 238 Class...End Class (wyrażenie) 239 Clipboard (klasa) 241 CLng (funkcja) 241 CLSCompliant (atrybut) 242 CObj (funkcja) 243 Collection (klasa) 244 Collection.Add (metoda) 245 Collection.Count (właściwość) 247 Collection.Item (właściwość) 248 Collection.Remove (metoda) 248 ColorDialog (klasa) 249 COMClass (atrybut) 251 Command (funkcja) 252 Const (wyrażenie) 254 Continue (wyrażenie) 255 Cos (funkcja) 256 Cosh (funkcja) 257 CreateObject (funkcja) 257 CSByte (funkcja) 259 CShort (funkcja) 260 CSng (funkcja) 261 CStr (funkcja) 262 CType (funkcja) 263 CUInt (funkcja) 265 CULng (funkcja) 266 CUShort (funkcja) 267 CurDir (funkcja) 268 Custom Event (wyrażenie) 268 6 | Spis treści
  • 6. DateAdd (funkcja) 270 DateDiff (funkcja) 272 DatePart (funkcja) 274 DateSerial (funkcja) 276 DateString (właściwość) 277 DateValue (funkcja) 278 Day (funkcja) 278 DDB (funkcja) 279 Debug (klasa) 280 Debug.Assert (metoda) 282 Debug.Listeners (właściwość) 283 Debug.Write (metoda) 284 Debug.WriteIf (metoda) 284 Debug.WriteLine (metoda) 285 Debug.WriteLineIf (metoda) 286 Declare (wyrażenie) 287 DefaultMember (atrybut) 290 Delegate (wyrażenie) 292 DeleteSetting (procedura) 294 Dim (wyrażenie) 296 Dir (funkcja) 300 DirectCast (funkcja) 302 Directory (klasa) 303 Directory.CreateDirectory (metoda) 304 Directory.Delete (metoda) 305 Directory.Exists (metoda) 306 Directory.GetCreationTime (metoda) 307 Directory.GetDirectories (metoda) 307 Directory.GetDirectoryRoot (metoda) 309 Directory.GetFiles (metoda) 310 Directory.GetFileSystemEntries (metoda) 311 Directory.GetLogicalDrives (metoda) 312 Directory.GetParent (metoda) 313 Directory.Move (metoda) 314 Do...Loop (wyrażenie) 315 E (pole) 316 End (wyrażenie) 317 Enum (wyrażenie) 319 Environ (funkcja) 321 EOF (funkcja) 323 Erase (wyrażenie) 324 Erl (właściwość) 324 Spis treści | 7
  • 7. Err (obiekt) 325 Err.Clear (metoda) 326 Err.Description (właściwość) 327 Err.GetException (metoda) 328 Err.HelpContext (właściwość) 328 Err.HelpFile (właściwość) 329 Err.LastDLLError (właściwość) 330 Err.Number (właściwość) 331 Err.Raise (metoda) 331 Err.Source (właściwość) 333 Error (wyrażenie) 333 ErrorToString (funkcja) 334 Event (wyrażenie) 334 Exception (klasa) 336 Exit (wyrażenie) 338 Exp (funkcja) 339 File (klasa) 339 File.Exists (metoda) 340 FileAttr (funkcja) 341 FileClose (procedura) 342 FileCopy (procedura) 343 FileDateTime (funkcja) 343 FileGet i FileGetObject (procedury) 344 FileLen (funkcja) 346 FileOpen (procedura) 347 FilePut i FilePutObject (procedury) 350 FileWidth (procedura) 351 Filter (funkcja) 352 Fix (funkcja) 353 Flags (atrybut) 354 Floor (funkcja) 354 FontDialog (klasa) 355 For...Next (wyrażenie) 357 For Each...Next (wyrażenie) 359 Format (funkcja) 360 FormatCurrency, FormatNumber i FormatPercent (funkcje) 364 FormatDateTime (funkcja) 365 FreeFile (funkcja) 366 Friend (słowo kluczowe) 367 Function (wyrażenie) 368 FV (funkcja) 372 GetAllSettings (funkcja) 373 8 | Spis treści
  • 8. GetAttr (funkcja) 374 GetChar (funkcja) 375 GetObject (funkcja) 376 GetSetting (funkcja) 377 GetType (operator) 379 Global (słowo kluczowe) 379 GoTo (wyrażenie) 380 Guid (atrybut) 382 Handles (słowo kluczowe) 382 Hashtable (klasa) 384 Hashtable.Add (metoda) 385 Hashtable.ContainsKey (metoda) 386 Hashtable.ContainsValue (metoda) 386 Hashtable.CopyTo (metoda) 387 Hashtable.Item (właściwość) 388 Hashtable.Keys (właściwość) 389 Hashtable.Remove (metoda) 389 Hashtable.Values (właściwość) 390 Hex (funkcja) 390 Hour (funkcja) 391 IEEERemainder (funkcja) 391 If...Then...Else (wyrażenie) 392 IIf (funkcja) 394 Implements (słowo kluczowe) 395 Implements (wyrażenie) 396 Imports (wyrażenie) 398 Inherits (wyrażenie) 399 Input (procedura) 400 InputBox (funkcja) 402 InputString (funkcja) 403 InStr (funkcja) 404 InStrRev (funkcja) 405 Int (funkcja) 406 Interface...End Interface (wyrażenie) 407 IPmt (funkcja) 410 IRR (funkcja) 411 Is (operator) 412 IsArray (funkcja) 413 IsDate (funkcja) 414 IsDBNull (funkcja) 415 IsError (funkcja) 416 IsNot (operator) 417 Spis treści | 9
  • 9. IsNothing (funkcja) 418 IsNumeric (funkcja) 419 IsReference (funkcja) 419 Join (funkcja) 420 Kill (procedura) 421 LBound (funkcja) 422 LCase (funkcja) 423 Left (funkcja) 423 Len (funkcja) 424 Like (operator) 425 LineInput (funkcja) 426 Loc (funkcja) 427 Lock (procedura) 428 LOF (funkcja) 430 Log (funkcja) 430 Log10 (funkcja) 432 LSet (funkcja) 432 LTrim (funkcja) 433 MarshalAs (atrybut) 434 Max (funkcja) 437 Me (słowo kluczowe) 438 Mid (funkcja) 439 Mid (wyrażenie) 440 Min (funkcja) 441 Minute (funkcja) 442 MIRR (funkcja) 442 MkDir (procedura) 443 Mod (operator) 444 Module...End Module (wyrażenie) 445 Month (funkcja) 446 MonthName (funkcja) 446 MsgBox (funkcja) 447 MTAThread (atrybut) 449 MyBase (słowo kluczowe) 450 MyClass (słowo kluczowe) 451 Namespace (wyrażenie) 453 New (słowo kluczowe) 453 Nothing (słowo kluczowe) 454 Now (właściwość) 455 NPer (funkcja) 455 NPV (funkcja) 457 Obsolete (atrybut) 458 10 | Spis treści
  • 10. Oct (funkcja) 459 Of (słowo kluczowe) 459 On Error (wyrażenie) 460 OpenFileDialog (klasa) 462 Operator (wyrażenie) 464 Option Compare (wyrażenie) 466 Option Explicit (wyrażenie) 467 Option Strict (wyrażenie) 468 Out (atrybut) 469 ParamArray (atrybut) 471 Partial (słowo kluczowe) 471 Partition (funkcja) 472 PI (pole) 474 Pmt (funkcja) 475 Pow (funkcja) 476 PPmt (funkcja) 476 Print i PrintLine (procedury) 478 Private (słowo kluczowe) 479 Property (wyrażenie) 480 Protected (słowo kluczowe) 484 Public (słowo kluczowe) 486 PV (funkcja) 487 QBColor (funkcja) 488 Queue (klasa) 489 Queue.Contains (metoda) 490 Queue.CopyTo (metoda) 491 Queue.Dequeue (metoda) 492 Queue.Enqueue (metoda) 493 Queue.Peek (metoda) 493 Queue.ToArray (metoda) 494 RaiseEvent (wyrażenie) 494 Randomize (procedura) 496 Rate (funkcja) 497 ReDim (wyrażenie) 498 Rem (wyrażenie) 500 RemoveHandler (wyrażenie) 501 Rename (procedura) 502 Replace (funkcja) 503 Reset (procedura) 504 Resume (wyrażenie) 505 Return (wyrażenie) 506 RGB (funkcja) 507 Spis treści | 11
  • 11. Right (funkcja) 508 RmDir (procedura) 509 Rnd (funkcja) 510 Round (funkcja) 511 RSet (funkcja) 512 RTrim (funkcja) 513 SaveFileDialog (klasa) 514 SaveSetting (procedura) 515 ScriptEngine (właściwość) 517 ScriptEngineBuildVersion (właściwość) 518 ScriptEngineMajorVersion (właściwość) 518 ScriptEngineMinorVersion (właściwość) 519 Second (funkcja) 519 Seek (funkcja) 520 Seek (procedura) 521 Select Case (wyrażenie) 522 Send, SendWait (metody) 524 SetAttr (procedura) 526 Shadows (słowo kluczowe) 528 Shared (słowo kluczowe) 528 Shell (funkcja) 529 Sign (funkcja) 531 Sin (funkcja) 532 Sinh (funkcja) 532 SLN (funkcja) 533 Space (funkcja) 534 SPC (funkcja) 534 Split (funkcja) 535 Sqrt (funkcja) 536 Stack (klasa) 537 Stack.Contains (metoda) 538 Stack.CopyTo (metoda) 539 Stack.Peek (metoda) 540 Stack.Pop (metoda) 541 Stack.Push (metoda) 541 Stack.ToArray (metoda) 542 STAThread (atrybut) 542 Static (wyrażenie) 543 Stop (wyrażenie) 543 Str (funkcja) 544 StrComp (funkcja) 545 StrConv (funkcja) 546 12 | Spis treści
  • 12. StrDup (funkcja) 547 StrReverse (funkcja) 548 Structure...End Structure (wyrażenie) 549 Sub (wyrażenie) 551 Switch (funkcja) 554 SYD (funkcja) 555 SyncLock (wyrażenie) 556 SystemTypeName (funkcja) 557 TAB (funkcja) 557 Tan (funkcja) 558 Tanh (funkcja) 559 ThreadStatic (atrybut) 560 Throw (wyrażenie) 561 TimeOfDay (właściwość) 562 Timer (właściwość) 562 TimeSerial (funkcja) 563 TimeString (właściwość) 564 TimeValue (funkcja) 565 Today (właściwość) 566 Trim (funkcja) 566 Try...Catch...Finally (wyrażenie) 567 TryCast (funkcja) 569 TypeName (funkcja) 570 TypeOf (operator) 572 UBound (funkcja) 573 UCase (funkcja) 573 Unlock (procedura) 574 Using...End Using (wyrażenie) 575 Val (funkcja) 577 VarType (funkcja) 577 VBFixedArray (atrybut) 579 VBFixedString (atrybut) 580 VbTypeName (funkcja) 581 WebMethod (atrybut) 582 WebService (atrybut) 583 Weekday (funkcja) 584 WeekdayName (funkcja) 585 While...End While (wyrażenie) 586 With...End With (wyrażenie) 587 WithEvents (słowo kluczowe) 588 Write i WriteLine (procedury) 588 Year (funkcja) 590 Spis treści | 13
  • 13. 13. Leksykon przestrzeni nazw My .................................................................................. 591 AllUsersApplicationData (właściwość) 592 AltKeyDown (właściwość) 593 Application (obiekt) 594 ApplicationContext (właściwość) 595 AssemblyName (właściwość) 596 Audio (obiekt) 597 AvailablePhysicalMemory (właściwość) 597 AvailableVirtualMemory (właściwość) 598 ButtonsSwapped (właściwość) 599 CapsLock (właściwość) 599 ChangeCulture (metoda) 600 ChangeUICulture (metoda) 601 ClassesRoot (właściwość) 602 Clear (metoda) 603 Clipboard (obiekt) 603 Clock (obiekt) 605 Close (metoda) 605 CombinePath (metoda) 606 CommandLineArgs (właściwość) 607 CommentTokens (właściwość) 608 CompanyName (właściwość) 609 Computer (obiekt) 610 ContainsAudio (metoda) 611 ContainsData (metoda) 611 ContainsFileDropList (metoda) 612 ContainsImage (metoda) 613 ContainsText (metoda) 613 CopyDirectory (metoda) 614 CopyFile (metoda) 616 Copyright (właściwość) 618 CreateDirectory (metoda) 619 CtrlKeyDown (właściwość) 620 Culture (właściwość) 620 CurrentConfig (właściwość) 621 CurrentDirectory (właściwość) 622 CurrentPrincipal (właściwość) 623 CurrentUser (właściwość) 624 CurrentUserApplicationData (właściwość) 625 DefaultFileLogWriter (właściwość) 626 DeleteDirectory (metoda) 627 DeleteFile (metoda) 629 14 | Spis treści
  • 14. Delimiters (właściwość) 630 Deployment (właściwość) 632 Description (właściwość) 633 Desktop (właściwość) 634 DirectoryExists (metoda) 634 DirectoryPath (właściwość) 635 DoEvents (metoda) 636 DownloadFile (metoda) 637 Drives (właściwość) 638 DynData (właściwość) 639 EndOfData (właściwość) 640 ErrorLine (właściwość) 641 ErrorLineNumber (właściwość) 642 FieldWidths (właściwość) 643 FileExists (metoda) 644 FileSystem (obiekt) 645 FindInFiles (metoda) 646 Forms (obiekt) 648 GetAudioStream (metoda) 649 GetData (metoda) 650 GetDataObject (metoda) 651 GetDirectories (metoda) 652 GetDirectoryInfo (metoda) 653 GetDriveInfo (metoda) 655 GetEnvironmentVariable (metoda) 656 GetFileDropList (metoda) 657 GetFileInfo (metoda) 658 GetFiles (metoda) 660 GetImage (metoda) 661 GetName (metoda) 662 GetParentPath (metoda) 663 GetTempFileName (metoda) 664 GetText (metoda) 665 GetValue (metoda) 666 GmtTime (właściwość) 667 HasFieldsEnclosedInQuotes (właściwość) 668 Info (obiekt składowy obiektu My.Application) 669 Info (obiekt składowy obiektu My.Computer) 670 InitializeWithWindowsUser (metoda) 670 InstalledUICulture (właściwość) 671 IsAuthenticated (właściwość) 672 IsAvailable (właściwość) 672 Spis treści | 15
  • 15. IsInRole (metoda) 673 IsNetworkDeployed (właściwość) 674 Keyboard (obiekt) 675 LineNumber (właściwość) 676 LoadedAssemblies (właściwość) 677 LocalMachine (właściwość) 678 LocalTime (właściwość) 679 Log (obiekt składowy przestrzeni nazw My) 680 Log (obiekt składowy obiektu My.Application) 680 MinimumSplashScreenDisplayTime (właściwość) 681 Mouse (obiekt) 682 MoveDirectory (metoda) 683 MoveFile (metoda) 684 My (przestrzeń nazw) 686 MyDocuments (właściwość) 687 MyMusic (właściwość) 688 MyPictures (właściwość) 689 Name (właściwość składowa obiektu My.Computer) 690 Name (właściwość składowa obiektu My.User) 690 Network (obiekt) 691 NetworkAvailabilityChanged (zdarzenie składowe obiektu My.Application) 692 NetworkAvailabilityChanged (zdarzenie składowe obiektu My.Computer.Network) 693 NumLock (właściwość) 694 OpenForms (właściwość) 695 OpenSerialPort (metoda) 696 OpenTextFieldParser (metoda) 698 OpenTextFileReader (metoda) 699 OpenTextFileWriter (metoda) 701 OSFullName (właściwość) 702 OSPlatform (właściwość) 703 OSVersion (właściwość) 704 PeekChars (metoda) 705 PerformanceData (właściwość) 706 Ping (metoda) 706 Play (metoda) 707 PlaySystemSound (metoda) 709 Ports (obiekt) 710 ProductName (właściwość) 711 ProgramFiles (właściwość) 711 Programs (właściwość) 712 ReadAllBytes (metoda) 713 16 | Spis treści
  • 16. ReadAllText (metoda) 714 ReadFields (metoda) 715 ReadLine (metoda) 716 ReadToEnd (metoda) 717 Registry (obiekt) 718 RenameDirectory (metoda) 719 RenameFile (metoda) 720 Request (obiekt) 721 Resources (obiekt) 722 Response (obiekt) 723 Run (metoda) 724 SaveMySettingsOnExit (właściwość) 725 Screen (właściwość) 726 ScrollLock (właściwość) 727 SendKeys (metoda) 727 SerialPortNames (właściwość) 730 SetAudio (metoda) 731 SetData (metoda) 732 SetDataObject (metoda) 733 SetDelimiters (metoda) 734 SetFieldWidths (metoda) 735 SetFileDropList (metoda) 736 SetImage (metoda) 737 SetText (metoda) 738 Settings (obiekt) 739 SetValue (metoda) 741 ShiftKeyDown (właściwość) 743 Shutdown (zdarzenie) 743 SpecialDirectories (obiekt) 744 SplashScreen (właściwość) 745 StackTrace (właściwość) 746 Startup (zdarzenie) 748 StartupNextInstance (zdarzenie) 749 Stop (metoda) 750 Temp (właściwość) 751 TextFieldParser (obiekt) 752 TextFieldType (właściwość) 753 TickCount (właściwość) 754 Title (właściwość) 755 TotalPhysicalMemory (właściwość) 756 TotalVirtualMemory (właściwość) 757 TraceSource (właściwość) 757 Spis treści | 17
  • 17. Trademark (właściwość) 759 TrimWhiteSpace (właściwość) 759 UICulture (właściwość) 760 UnhandledException (zdarzenie) 761 UploadFile (metoda) 762 User (obiekt) 764 Users (właściwość) 765 Version (właściwość) 766 WebServices (obiekt) 767 WheelExists (właściwość) 768 WheelScrollLines (właściwość) 769 WorkingSet (właściwość) 770 WriteAllBytes (metoda) 770 WriteAllText (metoda) 771 WriteEntry (metoda) 772 WriteException (metoda) 774 III Dodatki .................................................................................................. 777 A Elementy języka Visual Basic według kategorii ........................................................ 779 Obsługa tablic 780 Schowek 780 Obiekty kolekcji 781 Popularne okna dialogowe 782 Kompilacja warunkowa 782 Konwersja 782 Data i godzina 783 Diagnostyka 784 Deklaracja 784 Obsługa błędów 785 System plików 786 Operacje finansowe 787 Informacja 787 Wejście-wyjście 788 Zintegrowane środowisko programowania 789 Interakcja 789 Matematyka 790 Struktura programu i przepływ sterowania 791 Programowanie obiektowe i różne konstrukcje programowe 791 Rejestr 793 Operacje na łańcuchach 793 18 | Spis treści
  • 18. B Hierarchia przestrzeni nazw ......................................................................................795 Hierarchia przestrzeni nazw My 795 Hierarchia przestrzeni nazw System 801 C Stałe i typy wyliczeniowe .......................................................................................... 805 Stałe wbudowane Visual Basica 805 Klasa ControlChars 808 Typy wyliczeniowe Visual Basica 809 D Co dodano, a co zmieniono w Visual Basicu .NET 2002? .......................................... 815 Zmiany językowe wprowadzone w Visual Basicu .NET 2002 815 Zmiany dotyczące konstrukcji programistycznych 824 Przestarzałe konstrukcje programistyczne 826 Ustrukturalizowana obsługa wyjątków 827 Zmiany w technikach programowania obiektowego 827 E Co dodano, a co zmieniono w Visual Basicu .NET 2003? .......................................... 831 Zmiany językowe wprowadzone w Visual Basicu .NET 2003 831 F Co dodano, a co zmieniono w Visual Basicu 2005? ................................................. 833 Rozszerzenia istniejącej funkcjonalności 834 Przestrzeń nazw My 837 Pozostałe nowości 838 G Elementy Visual Basica 6, które nie są już obsługiwane ..........................................841 H Kompilator Visual Basica obsługiwany z poziomu wiersza poleceń .......................847 Podstawy kompilatora Visual Basica 847 Przełączniki wiersza poleceń 848 Stosowanie pliku odpowiedzi 853 Stałe kompilacji warunkowej 854 Skorowidz ....................................................................................................................857 Spis treści | 19
  • 19. ROZDZIAŁ 4. Zmienne i typy danych Mechanizmy odpowiedzialne za przetwarzanie danych są sercem wszystkich aplikacji pro- gramowych. Moglibyśmy oczywiście przetwarzać dane tak jak robi to procesor komputera, czyli bit po bicie, jednak praca nad odpowiednimi algorytmami szybko by nas znużyła — właśnie dlatego takie języki jak Visual Basic oferują rozmaite typy danych oraz implementacje narzędzi zarządzających danymi (z których każdy bazuje na jakimś podzbiorze możliwych wartości danych). W niniejszym rozdziale zajmiemy się typami danych, sposobami zarzą- dzania danymi przez te typy oraz technikami ich przetwarzania w języku Visual Basic i plat- formie .NET. Pojęcie „typ danych” nie jest tożsame z bardziej ogólnym terminem „typ” wykorzystywanym w rozmaitych aspektach w tej i innych publikacjach poświęconych technologii .NET. Cała koncepcja platformy .NET bazuje na pojęciu typu, czyli podstawowej konstrukcji danych obejmującej klasy, struktury, delegacje i inne wysokopoziomowe elementy wykorzystywane w procesie konstruowania aplikacji oraz podczas przekazywania danych pomiędzy progra- mami. Typy danych dostępne w platformie .NET bazują właśnie na tych ogólnie rozumianych typach (podobnie zresztą jak klasy budowane przez samych programistów). Typy danych oferują stosunkowo niewielki, ale bardzo istotny zbiór narzędzi przetwarzania danych pogru- powanych według podzbiorów możliwych wartości (zarządzanych w ramach poszczególnych typów danych). Typy danych Środowisko uruchomieniowe wspólnego języka platformy .NET (CLR) obejmuje między inny- mi wspólny system typów (CTS), który definiuje typy danych obsługiwane właśnie przez śro- dowisko CLR. Wszystkie języki programowania przystosowane do współpracy z platformą .NET muszą implementować przynajmniej podzbiory typów danych środowiska CLR (część języków implementuje wszystkie, np. Visual Basic począwszy od wydania z 2005 roku). W technologii .NET typy danych mają postać specjalnych klas i struktur, których egzemplarze reprezentują wartości danych należące do ograniczonych przedziałów (właściwych dla poszcze- gólnych typów). Przykładowo, typ danych Byte oferuje możliwość reprezentowania i zarzą- dzania 8-bitowymi wartościami całkowitoliczbowymi bez znaku, czyli liczbami z przedziału od 0 do 255. Egzemplarze tego typu nie mogą zawierać wartości spoza tego przedziału (pod- zbioru), ale przynajmniej z tym konkretnym podzbiorem radzą sobie znakomicie. Platforma .NET oferuje typy danych dla tych podzbiorów wartości, które są najczęściej wykorzystywane 77
  • 20. przez programistów podczas wytwarzania aplikacji. Za pomocą tych typów można reprezen- tować niemal dowolne kombinacje danych. Jeśli predefiniowane typy danych platformy .NET nie odpowiadają naszym potrzebom, możemy te typy wykorzystać w roli bloków składających się na naszą własną klasę zarządzającą danymi. Platforma .NET Framework implementuje blisko dwadzieścia podstawowych typów danych, z których większość zaprojektowano z myślą o przetwarzaniu liczb całkowitych i zmienno- przecinkowych. Rdzenne typy danych Visual Basica (znane jeszcze sprzed wprowadzenia plat- formy .NET) stanowią tylko opakowania dla wspomnianych typów podstawowych systemu CTS. Przykładowo, stosowany w Visual Basicu typ danych Integer jest opakowaniem struktury System.Int32. Jedną z wartości struktury Int32 jest stała MaxValue reprezentująca mak- symalną wartość numeryczną, którą można składować w tym typie danych. Oznacza to, że choć składowa MaxValue nie jest oficjalną częścią Visual Basica, pełna zależność typu danych Integer od wspomnianego typu podstawowego Int32 systemu CTS powoduje, że poniższa para wyrażeń zostanie prawidłowo skompilowana i wykonana: Dim usesInt32 As Integer MsgBox(usesInt32.MaxValue) ' Wyświetla 2147483647 Przed wydaniem wersji 2005 tylko niektóre spośród podstawowych typów danych platformy .NET były implementowane w Visual Basicu. Nawet mimo braku odpowiednich opakowań Visual Basica, wcześniejsze wydania tego języka (oczywiście już w ramach platformy .NET) udostępniały „nieopakowane” typy danych systemu CTS. Ponieważ podstawowe typy danych platformy .NET mają postać klas i struktur, można z nich korzystać w Visual Basicu dokład- nie tak jak z innych klas czy struktur. Typy wartościowe i referencyjne Typy danych w języku Visual Basic można podzielić pomiędzy dwie dość ogólne kategorie: typy wartościowe (ang. data types) oraz typy referencyjne (ang. reference types). Typy wartościo- we różnią się od typów referencyjnych przede wszystkim sposobem składowania w pamięci. Pamięć przydzielana zmiennej typu wartościowego zawiera właściwą wartość tej zmiennej. Przykładowo, w czasie wykonywania poniższego wyrażenia: Dim simpleValue As Integer = 5 zostanie zarezerwowane miejsce w pamięci potrzebne do składowania przypisywanej warto- ści 5. Inaczej jest w przypadku typów referencyjnych, gdzie pod adresami pamięci przydzielo- nymi tym zmiennym są składowane adresy innych bloków pamięci, w których znajdują się wła- ściwe dane. Mechanizm stosowany w typach referencyjnych przypomina trochę usługę pocztową polegającą na przesyłaniu pod inny adres listów oryginalnie kierowanych do okre- ślonego odbiorcy. Przykładowo, dla poniższej deklaracji typu referencyjnego: Dim somewhereElse As New MyCustomClass kompilator Visual Basica utworzy w pamięci egzemplarz klasy MyCustomClass, po czym przy- pisze zmiennej somewhereElse rzeczywisty adres w pamięci tego egzemplarza. Programistom, którzy mają doświadczenie w pracy ze wskaźnikami oferowanymi przez takie języki jak C++, zrozumienie mechanizmu stosowanego w Visual Basicu nie powinno sprawić najmniejszych problemów, ponieważ oba rozwiązania są bardzo podobne. Najkrócej mówiąc, zmienne typów wartościowych zawierają dane, natomiast zmienne typów referencyjnych tylko na te dane wskazują. 78 | Rozdział 4. Zmienne i typy danych
  • 21. Różnice pomiędzy typami wartościowymi a typami referencyjnymi powodują szereg konse- kwencji — jedną z najważniejszych jest sposób wykonywania popularnych operacji przypi- sania. Przeanalizujmy poniższą klasę, która zawiera tylko jedno pole składowe: Public Class SimpleClass Public Age As Short End Class oraz strukturę będącą odpowiednikiem tej klasy: Structure SimpleStruct Public Age As Short End Structure W przeciwieństwie do struktur, które są typami wartościowymi, klasy są typami referencyj- nymi. Poniższy kod ilustruje podstawową różnicę w korzystaniu z tej pary podobnych, ale mimo wszystko różnych typów: ' ----- Deklaruje cztery zmienne, po dwie dla każdego z typów. Dim refType1 As SimpleClass Dim refType2 As SimpleClass Dim valType1 As SimpleStruct Dim valType2 As SimpleStruct ' ----- W pierwszej kolejności skoncentrujemy się na typach referencyjnych. ' Przypisanie refType2 = refType1 spowoduje, że obie zmienne refType2 ' będą wskazywały na ten sam adres w pamięci. Od tej pory zmiany ' składowych zmiennej refType1 będą miały wpływ na składowe zmiennej ' refType2 i odwrotnie. Obie zmienne współdzielą ten sam egzemplarz. refType1 = New SimpleClass refType1.Age = 20 refType2 = refType1 refType2.Age = 30 Debug.WriteLine(refType1.Age) ' --> Wyświetla 30 Debug.WriteLine(refType2.Age) ' --> Wyświetla 30 ' ----- Przyjrzyjmy się teraz typom wartościowym. Przypisanie valType2 = valType1 ' powoduje wykonanie kopii składowych zmiennej valType1. Od tej pory zmiany ' składowych jednej z tych zmiennych nie będą miały wpływu na wartości ' składowych drugiej zmiennej. valType1 = New SimpleStruct valType1.Age = 20 valType2 = valType1 valType2.Age = 30 Debug.Writeline(valType1.Age) ' --> Wyświetla 20 Debug.Writeline(valType2.Age) ' --> Wyświetla 30 W pewnym sensie obie operacje przypisania jednej zmiennej drugiej zmiennej realizują to samo zadanie — kopiują wartość reprezentowaną przez zmienną użytą po prawej stronie do zmien- nej na lewo od operatora przypisania. Ponieważ jednak rzeczywistą wartością typu referen- cyjnego (w tym przypadku zmiennej refType1) jest adres w pamięci, właśnie adres został skopio- wany do zmiennej refType2. Ponieważ obie zmienne wskazują na ten sam obszar w pamięci (miejsce przechowywania składowych obiektu klasy SimpleClass), w praktyce zmienne ref- Type1 i refType2 współdzielą jeden zbiór składowych. Przypisanie jednej zmiennej typu wartościowego (valType1) innej zmiennej typu wartościowego (valType2) także polega na skopiowaniu wartości zmiennej użytej na prawo od operatora przy- pisania do zmiennej użytej z lewej strony tego operatora. Różnica polega na tym, że zmienna valType1 zawiera rzeczywiste składowe (nie adres miejsca ich przechowywania w pamięci). Oznacza to, że zmienna docelowa valType2 zawiera odrębną kopię tych składowych (w tym przypadku jedynej składowej Age). Typy danych | 79
  • 22. Wyzerowanie zmiennej typu referencyjnego wymaga przypisania jej wartości Nothing. Typy wartościowe zawsze reprezentują jakieś wartości (nawet jeśli są to same zera), zatem w ich przypadku przypisywanie „wartości” Nothing nie jest możliwe. Wszystkie podstawowe typy danych Visual Basica, które zarządzają wartościami numerycz- nymi (czyli np. Integer oraz Double), są typami wartościowymi. Typ danych String jest co prawda przykładem typu referencyjnego, jednak z perspektywy programisty funkcjonuje dokładnie tak jak typy wartościowe. Za każdym razem gdy przypisujemy jedną zmienną łańcuchową innej, wbrew pozorom w łańcuchu docelowym nie jest zapisywana referencja do pierwszego łańcucha (jak w przypadku innych typów referencyjnych). Wynika to z faktu, że stosowana w Visual Basicu implementacja typu danych String każdorazowo (zarówno pod- czas przypisywania, jak i modyfikowania) tworzy zupełnie nowy egzemplarz oryginalnego łańcucha. Podstawowe typy danych Visual Basica: przegląd Język programowania Visual Basic począwszy od wersji 2005 implementuje wszystkie pod- stawowe typy danych platformy .NET Framework (a konkretnie wspólnego systemu typów, CTS). Okazuje się, że podstawowe typy danych oferują bardzo szeroki zakres funkcjonalności i pozwalają zarządzać niemal wszystkimi kategoriami danych. Typy danych należące do sys- temu CTS można podzielić na pięć grup (według rodzaju zarządzanych danych): Dane logiczne Pojedynczy typ danych, który obejmuje tylko jeden bit reprezentujący prawdę lub fałsz (odpowiednio True lub False). Dane znakowe Visual Basic oferuje typy danych zarządzające zarówno pojedynczymi znakami, jak i dłu- gimi łańcuchami znaków. Dane czasu i daty Pojedynczy typ danych zarządzający wartościami reprezentującymi zarówno datę, jak i godzinę. Dane zmiennoprzecinkowe Rozmaite typy danych reprezentujące wartości zmiennoprzecinkowe — każdy z tych typów zarządza ograniczonym podzbiorem liczb wymiernych. Niektóre z tych typów oferują więk- szą precyzję matematyczną od pozostałych. Dane całkowitoliczbowe Ta kategoria obejmuje wiele całkowitoliczbowych typów danych, które umożliwiają skła- dowanie liczb całkowitych należących do właściwego (zależnego od typu) przedziału (od wartości minimalnej do maksymalnej). Część typów danych całkowitoliczbowych obsłu- guje wartości ujemne. W dalszej części tego punktu przedstawimy definicje i stosowne komentarze do każdej z wy- mienionych powyżej kategorii typów danych obsługiwanych przez Visual Basic. Typ danych Boolean Podstawowe fakty Podstawowy typ .NET: System.Boolean Implementacja: Typ wartościowy (struktura) 80 | Rozdział 4. Zmienne i typy danych
  • 23. Ilość zajmowanej pamięci: 2 bajty Zakres wartości: True lub False Typ danych Boolean może reprezentować tylko dwie wartości (True lub False). W języku Visual Basic mamy do dyspozycji słowa kluczowe True i False, które są stosowane w roli warto- ści zmiennych typu Boolean. Zmiennym tego typu można też przypisywać wyniki dowol- nych operacji logicznych. Kiedy wartość numeryczna jest konwertowana na wartość typu Boolean, wszystkie wartości różne od zera są przekształcane w wartość True, a jedyną wartością tłumaczoną na False jest zero. W razie konwersji w drugą stronę wartość False jest zamieniana na zero, natomiast wartość True jest zamieniana na liczbę –1. (Ta część funkcjonalności odróżnia Visual Basica od pozostałych języków platformy .NET, które konwertują wartość True na 1. W Visual Basicu zastosowano w tej roli liczbę –1, aby zapewnić zgodność wstecz. W razie współdzielenia danych logicznych pomiędzy komponentami napisanymi w różnych językach platformy .NET, środo- wisko uruchomieniowe .NET Framework i tak automatycznie przekształci te wartości w spo- sób gwarantujący pełną zgodność). Typ danych Byte Podstawowe fakty Podstawowy typ .NET: System.Byte Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 1 bajt Zakres wartości: Od 0 do 255 (bez znaku) Typ danych Byte jest najmniejszym dostępnym w Visual Basicu typem całkowitoliczbowym bez znaku. Mimo bardzo niewielkiego przedziału obsługiwanych wartości zmienne typu Byte doskonale zdają egzamin podczas pracy z nieprzetworzonymi danymi binarnymi. Typ danych Char Podstawowe fakty Podstawowy typ .NET: System.Char Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 2 bajty Zakres wartości: Kody znaku z przedziału od 0 do 65535 (bez znaku) Typ danych Char reprezentuje pojedynczy, 16-bitowy znak Unicode. Wszystkie znaki w plat- formie .NET są reprezentowane właśnie za pomocą kodów 16-bitowych, co oczywiście wy- starczy do obsługi języków wymagających stosowania 2-bajtowego zbioru znaków (ang. Double- -Byte Character Set — DBCS), czyli np. języka japońskiego. Wersje Visual Basica sprzed wprowa- dzenia platformy .NET nie zawierały żadnego odpowiednika typu danych char. Stosując stałe wartości typu Char, należy do nich dołączać (za cudzysłowem zamykającym) pojedynczą literę c: Dim singleLetter As Char = "A"c Typy danych | 81
  • 24. Zmienna łańcuchowa (typu String), która zawiera tylko jeden znak, nie jest tożsama ze zmienną typu Char zawierającą ten sam znak. Ponieważ są to dwa zupełnie różne typy, ewentualne przenoszenie danych pomiędzy zmiennymi tych typów wymaga stosownej kon- wersji (jeśli włączono opcję Option Strict). Typ danych DateTime Podstawowe fakty Podstawowy typ .NET: System.DateTime Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 8 bajtów Zakres wartości: Od 1 stycznia 1 roku n.e. do 31 grudnia 9999 roku n.e. (w kalendarzu gregoriańskim) Wartości reprezentujące daty i czas mają postać 64-bitowych, długich liczb całkowitych zgod- nych ze standardem IEEE. Za pomocą tak długich liczb można reprezentować daty z prze- działu od 1 stycznia 1 roku n.e. do 31 grudnia 9999 roku n.e. oraz godziny z przedziału od 0:00:00 do 23:59:59. Odpowiednie wartości reprezentują liczbę „tyknięć”, które upłynęły od 1 sty- cznia 1 roku n.e. Każde takie „tyknięcie” odpowiada 100 nanosekundom. Stałe daty należy umieszczać pomiędzy dwoma znakami krzyżyków (#): Dim independenceDay As Date = #7/4/1776# Typ danych Decimal Podstawowe fakty Podstawowy typ .NET: System.Decimal Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 12 bajtów Zakres wartości: +/–79 228 162 514 264 337 593 543 950 335 bez części dziesiętnej; +/–7.9228162514264337593543950335 z 28 miejscami po przecinku; najmniejsza wartość różna od zera wynosi +/–0.0000000000000000000000000001 Wartości typu danych Decimal są składowane w formie 96-bitowych liczb całkowitych ze znakiem; reprezentacja tych wartości dodatkowo obejmuje wewnętrzny (obsługiwany i sto- sowany w pełni automatycznie) współczynnik skali z przedziału od 0 do 28. Takie rozwią- zanie zapewnia wysoki poziom precyzji matematycznej w przypadku liczb należących do odpowiedniego przedziału wartości (typ Decimal szczególnie dobrze sprawdza się w przypadku danych walutowych). Na końcu wartości stałych typu Decimal należy umieszczać albo pojedynczą literę D, albo znak @: Dim startingValue As Decimal = 123.45D Dim endingValue As Decimal = 543.21@ Znak @ można stosować także do oznaczania deklarowanych zmiennych jako egzemplarzy typu Decimal: Dim startingValue@ = 123.45D 82 | Rozdział 4. Zmienne i typy danych
  • 25. Składowe typu danych Decimal nazwane MaxValue i MinValue reprezentują granice obsłu- giwanego przedziału wartości (odpowiednio wartość maksymalną i minimalną). W implementacjach Visual Basica sprzed wprowadzenia technologii .NET typ danych Deci- mal w praktyce nie stanowił odrębnego, autonomicznego typu danych — był podtypem typu danych Variant. Dopiero w wersjach kwalifikujących Visual Basic do rodziny języków plat- formy .NET zaimplementowano typ Decimal w formie pełnowartościowego typu danych. Typ danych Double Podstawowe fakty Podstawowy typ .NET: System.Double Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 8 bajtów Zakres wartości: Od –1.79769313486231E+308 do –4.94065645841247E-324 w przypadku liczb ujemnych; od 4.94065645841247E–324 do 1.79769313486232E+308 w przypadku liczb dodatnich Wartości typu Double są zgodne ze standardem IEEE dla 64-bitowych (8-bajtowych) liczb zmiennoprzecinkowych podwójnej precyzji ze znakiem. Mimo ogromnego przedziału obsłu- giwanych wartości, stosując typ danych Double musimy się liczyć z utratą precyzji w pew- nych obliczeniach matematycznych. Stałe egzemplarze typu danych Double należy oznaczać wielką literą R lub znakiem krzyżyka (#) dołączanym bezpośrednio po wartościach numerycznych: Dim startingValue As Double = 123.45R Dim endingValue As Double = 543.21# Znak krzyżyka (#) można stosować także do oznaczania deklarowanych zmiennych jako egzem- plarzy typu Double: Dim startingValue# = 123.45R Typ danych Int32 (Integer) Podstawowe fakty Podstawowy typ .NET: System.Int32 Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 4 bajty Zakres wartości: Od –2 147 483 648 do 2 147 483 647 Typ danych Integer umożliwia reprezentowanie 32-bitowych liczb całkowitych ze znakiem. Właśnie tyle wynosi rdzenna długość słowa w procesorach 32-bitowych, zatem stosowanie tego rodzaju wartości powinno się przekładać na nieznacznie wyższą wydajność w porówna- niu z pozostałymi typami całkowitoliczbowymi. W wersjach Visual Basica sprzed wprowadzenia platformy .NET zmienne i stałe typu Integer zajmowały tylko 16 bitów i — tym samym — mogły służyć do reprezentowania liczb całko- witych z dużo mniejszego przedziału. W wersjach języka Visual Basic wchodzących w skład rodziny języków platformy .NET dodatkowo mamy do dyspozycji typ danych Short, czyli 16-bitowy typ całkowitoliczbowy ze znakiem. Typy danych | 83
  • 26. Stałe egzemplarze typu Integer można opcjonalnie oznaczać wielką literą I lub znakiem procenta (%) dołączanym na końcu wartości numerycznej: Dim startingValue As Integer = 123I Dim endingValue As Integer = 543% Znak procenta (%) można stosować także do oznaczania deklarowanych zmiennych jako egzem- plarzy typu Integer: Dim startingValue% = 123I Typ danych Int64 (Long) Podstawowe fakty Podstawowy typ .NET: System.Int64 Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 8 bajtów Zakres wartości: Od –9 223 372 036 854 775 808 do 9 223 372 036 854 775 807 Long jest 64-bitowym typem danych całkowitoliczbowych ze znakiem. W wersjach Visual Basica sprzed wprowadzenia platformy .NET zmienne i stałe typu Long zajmowały tylko 32 bity i tym samym mogły służyć do reprezentowania liczb całkowitych z dużo mniejszego przedziału. W wersjach języka Visual Basic wchodzących w skład rodziny języków platformy .NET mamy do dyspozycji typ danych Integer, czyli 32-bitowy typ całkowitoliczbowy ze znakiem. Stałe egzemplarze typu Long należy oznaczać wielką literą L lub znakiem & dołączanym na końcu wartości numerycznej: Dim startingValue As Long = 123L Dim endingValue As Long = 543& Znak & można stosować także do oznaczania deklarowanych zmiennych jako egzemplarzy typu Long: Dim startingValue& = 123L Stosując znak & do oznaczania stałych typu Long, w żadnym razie nie należy pozostawiać spacji pomiędzy wartością całkowitoliczbową a tym znakiem, ponieważ znak & dodatkowo pełni w Visual Basicu funkcję operatora konkatenacji łańcuchów. Typ danych Object Podstawowe fakty Podstawowy typ .NET: System.Object Implementacja: Typ referencyjny (klasa) Ilość zajmowanej pamięci: 4 bajty Zakres wartości: Zmienna typu Object może reprezentować dowolny typ Object jest uniwersalnym typem danych, co oznacza, że zmienna typu Object może się odwo- ływać do danych (wskazywać na dane) dowolnego innego typu danych. Przykładowo, egzem- plarz klasy Object może wskazywać na wartość typu Long, wartość typu String lub egzem- plarz dowolnej innej klasy. Dim amazingVariable As Object amazingVariable = 123L amazingVariable = "Czyż to nie wspaniałe?" amazingVariable = New MyCustomClass 84 | Rozdział 4. Zmienne i typy danych
  • 27. Warto pamiętać, że ze stosowaniem zmiennych typu Object wiążą się pewne koszty w wy- miarze wydajności oprogramowania. Visual Basic nie może związać właściwych składowych reprezentujących dane ze zmienną typu Object w czasie kompilacji, co oznacza, że odpo- wiednie łączenie musi nastąpić w czasie wykonywania programu — to z kolei powoduje, że przetwarzanie metod związanych z tym obiektem wymaga większej ilości kodu. Opisywana technika bywa nazywana późnym wiązaniem (ang. late binding). Deklarowanie obiektów z wła- ściwymi (konkretnymi) typami danych skutkuje wczesnym wiązaniem (ang. early binding), ponieważ za zarządzanie związkami wszystkich składowych odpowiada kompilator. Przy- kładowo, poniższy fragment kodu: Dim lateBound As Object . . . lateBound = New MyCustomClass lateBound.SomeMethod( ) wymusi na aplikacji dopasowanie zmiennej lateBound do składowej SomeMethod klasy MyCu- stomClass w czasie wykonywania. Przedstawione rozwiązanie jest więc dużo mniej wydajne od mechanizmu zastosowanego poniżej: Dim earlyBound As MyCustomClass . . . earlyBound = New MyCustomClass earlyBound.SomeMethod( ) W wersjach języka Visual Basic sprzed wprowadzenia technologii .NET programista miał do dyspozycji funkcję VarType, która identyfikowała konkretny podtyp wartości typu Variant. Okazuje się, że funkcja VarType istnieje także w kolejnych wersjach Visual Basica .NET i służy do identyfikacji faktycznych typów zmiennych lub wartości. Klasa System.Object (i klasy potomne, czyli wszystkie klasy w technologii .NET) dodatkowo udostępnia metodę GetType, która zwraca informację o prawdziwym typie danego obiektu. Chociaż wymienione rozwią- zania można stosować dla dowolnych typów danych, ich przydatność jest szczególnie widoczna właśnie w przypadku obiektów typu Object. Typ danych SByte Podstawowe fakty Podstawowy typ .NET: System.SByte Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 1 bajt Zakres wartości: Od —128 do 127 Nowość w wersji 2005. SByte jest najmniejszym typem danych całkowitoliczbowych ze zna- kiem obsługiwanym przez Visual Basica. Typ SByte jest więc odpowiednikiem opisanego wcze- śniej typu danych Byte (bez znaku) obejmującym znak. SByte jest jednym z czterech typów danych dodanych do języka programowania Visual Basic w wydaniu z roku 2005, które nie są wymienione w minimalnej specyfikacji wspólnego języka (CLS). W związku z tym, komponenty i aplikacje zbudowane według zaleceń tego minimal- nego standardu mogą nie być kompatybilne z aplikacjami wykorzystującymi ten typ danych. Typy danych | 85
  • 28. Typ danych Int16 (Short) Podstawowe fakty Podstawowy typ .NET: System.Int16 Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 2 bajty Zakres wartości: Od —32768 do 32767 Short jest 16-bitowym typem danych całkowitoliczbowych ze znakiem. W wersjach języka Visual Basic sprzed wprowadzenia technologii .NET funkcję 16-bitowego typu całkowitolicz- bowego ze znakiem pełnił inny typ danych, Integer; typ danych Short w ogóle nie wystę- pował w tamtych wydaniach Visual Basica. Stałe egzemplarze typu Short należy oznaczać wielką literą S dołączaną na końcu wartości numerycznej: Dim startingValue As Short = 123S Typ danych Single Podstawowe fakty Podstawowy typ .NET: System.Single Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 4 bajty Zakres wartości: Od –3.402823E+38 do –1.401298E–45 w przypadku liczb ujemnych; od 1.401298E–45 do 3.402823E+38 w przypadku liczb dodatnich Wartości typu Single są zgodne ze standardem IEEE dla 32-bitowych (4-bajtowych) liczb zmiennoprzecinkowych pojedynczej precyzji ze znakiem. Mimo stosunkowo dużego prze- działu obsługiwanych wartości, stosując typ danych Single, musimy się liczyć z utratą precyzji w pewnych obliczeniach matematycznych. Stałe egzemplarze typu danych Single należy oznaczać wielką literą F lub znakiem wykrzyk- nika (!) dołączanym bezpośrednio po wartościach numerycznych: Dim startingValue As Single = 123.45F Dim endingValue As Single = 543.21! Znak wykrzyknika (!) można stosować także do oznaczania deklarowanych zmiennych jako egzemplarzy typu Single: Dim startingValue! = 123.45F Typ danych String Podstawowe fakty Podstawowy typ .NET: System.String Implementacja: Typ referencyjny (klasa) Ilość zajmowanej pamięci: 10 + (2 * długość_łańcucha) bajtów Zakres wartości: Od zera do około dwóch miliardów znaków Unicode Typ danych String umożliwia reprezentowanie łańcuchów znakowych zmiennej długości złożonych maksymalnie z około dwóch miliardów znaków. 86 | Rozdział 4. Zmienne i typy danych
  • 29. Wszystkie łańcuchy w technologii .NET są niezmienne (ang. immutable). Oznacza to, że warto- ści raz przypisanej zmiennej łańcuchowej nie można zmieniać. Kiedy modyfikujemy zawartość łańcucha, typ danych String zwraca nowy egzemplarz uwzględniający wprowadzone zmiany. Zmienna String zawierająca pojedynczy znak nie jest tożsama ze zmienną typu Char zawie- rającą ten sam pojedynczy znak. Ponieważ są to dwa zupełnie różne typy, ewentualne prze- noszenie danych pomiędzy zmiennymi tych typów wymaga stosownej konwersji (jeśli włą- czono opcję Option Strict). Typ danych UInt32 (UInteger) Podstawowe fakty Podstawowy typ .NET: System.Int32 Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 4 bajty Zakres wartości: Od 0 do 4 294 967 295 (bez znaku) Nowość w wersji 2005. UInteger jest 32-bitowym typem danych całkowitoliczbowych bez znaku. Typ UInteger jest więc odpowiednikiem bez znaku opisanego wcześniej typu danych Integer (ze znakiem). UInteger jest jednym z czterech typów danych dodanych do języka programowania Visual Basic w wydaniu z roku 2005, które nie są wymienione w minimalnej specyfikacji wspólnego języka (CLS). W związku z tym, komponenty i aplikacje zbudowane według zaleceń tego minimalnego standardu mogą nie być kompatybilne z aplikacjami wykorzystującymi ten typ danych. Typ danych UInt64 (ULong) Podstawowe fakty Podstawowy typ .NET: System.Int64 Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 8 bajtów Zakres wartości: Od 0 do 18 446 744 073 709 551 615 (bez znaku) Nowość w wersji 2005. ULong jest 64-bitowym typem danych całkowitoliczbowych bez zna- ku. Typ ULong jest więc odpowiednikiem bez znaku opisanego wcześniej typu danych Long (ze znakiem). ULong jest jednym z czterech typów danych dodanych do języka programowania Visual Basic w wydaniu z roku 2005, które nie są wymienione w minimalnej specyfikacji wspólnego języka (CLS). W związku z tym, komponenty i aplikacje zbudowane według zaleceń tego minimal- nego standardu mogą nie być kompatybilne z aplikacjami wykorzystującymi ten typ danych. Typ danych UInt16 (UShort) Podstawowe fakty Podstawowy typ .NET: System.Int64 Implementacja: Typ wartościowy (struktura) Ilość zajmowanej pamięci: 2 bajty Zakres wartości: Od 0 do 65535 (bez znaku) Typy danych | 87
  • 30. Nowość w wersji 2005. UShort jest 16-bitowym typem danych całkowitoliczbowych bez znaku. Typ UShort jest więc odpowiednikiem bez znaku opisanego wcześniej typu danych Short (ze znakiem). UShort jest jednym z czterech typów danych dodanych do języka programowania Visual Basic w wydaniu z roku 2005, które nie są wymienione w minimalnej specyfikacji wspólnego języka (CLS). W związku z tym, komponenty i aplikacje zbudowane według zaleceń tego minimal- nego standardu mogą nie być kompatybilne z aplikacjami wykorzystującymi ten typ danych. Typy danych definiowane przez użytkownika Chociaż pojedyncze zmienne w zdecydowanej większości przypadków zaspokajają potrzeby programistów, nierzadko bardziej efektywnym rozwiązaniem jest łączenie wielu podstawowych wartości danych w ramach logicznych grup. Te niestandardowe typy danych (definiowane przez użytkownika) rozszerzają zbiór podstawowych typów danych o nowe typy dostosowane do potrzeb konkretnych programów. Wersje języka Visual Basic sprzed wprowadzenia technologii .NET oferowały możliwość two- rzenia typów danych definiowanych przez użytkownika za pośrednictwem wyrażenia Type. Budowane w ten sposób struktury danych były zwykłymi grupami zmiennych pozbawio- nymi jakiejkolwiek funkcjonalności (oczywiście poza możliwością ustawiania i odczytywania wartości reprezentowanych w poszczególnych składowych). W wydaniach Visual Basica wchodzących w skład platformy .NET Framework znacznie rozszerzono tego rodzaju mechani- zmy, implementując możliwość definiowania kodu zarówno we wspomnianych strukturach danych, jak i podstawowych elementach platformy .NET. Typy znane z Visual Basica 6 zastą- piono konstrukcjami powszechnie stosowanymi w technologii .NET — strukturami (definio- wanymi ze słowem kluczowym Structure). Podstawową konstrukcją gromadzącą kod i dane w platformie .NET jest klasa. Klasy pod wieloma względami przypominają struktury, ale są wolne od pewnych ograniczeń, które dotyczą wyłącznie struktur. Bodaj najważniejszą różnicą dzielącą struktury od klas jest to, że w przeciwieństwie do klas (które implementują typy referencyjne), struktury implementują typy wartościowe (dziedziczące bezpośrednio po typie System.ValueType). Aby zadeklarować strukturę, należy użyć wyrażenia Structure: [Public|Private|Friend] Structure structureName deklaracje składowych End Structure Składowymi struktury mogą być pola, właściwości, metody, zdarzenia dzielone, typy wylicze- niowe oraz inne, zagnieżdżone struktury. Każda ze składowych musi zostać zadeklarowana z jednym z trzech modyfikatorów dostępu: Public, Private lub Friend. Najprostszym i najczęściej spotykanym zastosowaniem struktur jest grupowanie wzajemnie powiązanych zmiennych (nazywanych polami). Przykładowo, w naszym programie możemy korzystać z prostej struktury definiującej podstawowe informacje o jednej osobie: Structure Person Public Name As String Public Address As String Public City As String Public State As String Public Zip As String Public Age As Short End Structure 88 | Rozdział 4. Zmienne i typy danych
  • 31. Poniżej przedstawiono standardową deklarację definiującą zmienną typu Person: Dim onePerson As Person Dostęp do składowych struktury wymaga użycia standardowej składni „z kropką”, która jest stosowana także w przypadku składowych klas: onePerson.Name = "Beethoven" Bardziej złożone struktury mogą zawierać zarówno proste pola składowe, jak i właściwości: Public Structure NameAndState ' ----- Pola publiczne i prywatne. Public Name As String Private theState As String Public Function ShowAll( ) As String ' ----- Metoda publiczna. Wyświetla wszystkie składowane wartości. If (theState = "") And (Name = "") Then Return "<No Name> from <Nowhere>" ElseIf (theState = "") Then Return Name & " from <Nowhere>" ElseIf (Name = "") Then Return "<No Name> from " & theState Else Return Name & " from " & theState End If End Function Public Property State( ) As String ' ----- Właściwość publiczna. Ogranicza zbiór wartości reprezentujących stany. Get Return theState End Get Set(ByVal value As String) If (Len(value) = 2) Then theState = UCase(value) Else Throw New System.ArgumentException( _ "Stan musi być reprezentowany przez dwa znaki.", "State") End If End Set End Property End Structure Egzemplarze tej struktury mogą być od tej pory tworzone i wykorzystywane dokładnie tak jak egzemplarze klas: Dim onePerson As New NameAndState onePerson.Name = "Donna" onePerson.State = "CA" MsgBox(onePerson.ShowAll()) Struktury mogą być przekazywane na wejściu funkcji w formie argumentów lub wykorzysty- wane w roli typów zwracanych przez funkcje. Chociaż struktury pod wieloma względami przy- pominają klasy, nie obsługują szeregu rozwiązań znanych z klas: • Struktury nie mogą ani dziedziczyć po innych strukturach, ani same nie mogą być dzie- dziczone. • Wszystkie konstruktory struktur muszą pobierać parametry wejściowe. • Struktury nie mogą definiować destruktorów (metoda Finalize i tak nigdy nie jest wy- woływana). Typy danych | 89
  • 32. • Deklaracje składowych nie mogą inicjalizować ich wartości, stosować konstrukcji skład- niowej As New ani określać początkowego rozmiaru tablic. Szczegółowe omówienie terminologii programowania można znaleźć w rozdziale 3. Konwersja typów danych Proces konwersji wartości jednego typu na wartość innego typu nazywamy rzutowaniem (ang. casting) lub po prostu konwersją. Techniki konwersji mogą być stosowane dla wartości sta- łych, zmiennych lub wyrażeń określonego typu. Język programowania Visual Basic oferuje szereg funkcji konwertujących, które rzutują wartości jednego typu danych do postaci ich odpo- wiedników innego typu danych: Dim miniSize As Byte = 6 Dim superSize As Long superSize = CLng(miniSize) ' Konwertuje wartość zmiennej typu Byte na wartość typu Long. superSize = CLng("12") ' Konwertuje stałą typu String na wartość typu Long. Rzutowania mogą mieć charakter działań rozszerzających lub zawężających. Rzutowanie rozszerzające (ang. widening cast) ma miejsce wtedy, gdy docelowy typ danych może z powo- dzeniem reprezentować wszystkie możliwe wartości typu źródłowego (z taką sytuacją mamy do czynienia np. wtedy, gdy konwertujemy wartość typu Short na wartość typu Integer lub wartość typu Integer na wartość typu Double). Rzutowanie rozszerzające nigdy nie powoduje utraty danych. Rzutowanie zawężające (ang. narrowing cast) polega na konwersji oryginal- nego typu danych na typ, który nie może reprezentować wszystkich możliwych danych typu źródłowego. Rzutowanie zawężające może prowadzić do utraty części danych lub wręcz błędu konwersji. Konwersje typów w Visual Basicu mogą być realizowane na dwa sposoby: jawnie (wprost) lub w ukryciu. Konwersja niejawna (ang. implicit conversion) jest realizowana przez kompilator, jeśli okoliczności na to pozwalają (i jeśli samo rzutowanie jest prawidłowe). Przykładowo, jeśli umieścimy w naszej aplikacji następującą sekwencję wyrażeń: Dim smallerData As Integer = 3948 Dim largerData As Long largerData = smallerData wartość zmiennej smallerData automatycznie zostanie rzutowana do większego typu danych Long (wykorzystywanego przez zmienną largerData). Ten rodzaj konwersji niejawnej po części jest uzależniony od ustawienia wyrażenia Option Strict. Wyrażenie Option Strict powinno się znajdować na samym początku pliku z kodem źródłowym (przed właściwym kodem klasy): Option Strict {On | Off} Jeśli opcja Option Strict jest włączona (On), kompilator będzie automatycznie wykonywał tylko rzutowania rozszerzające, co oznacza, że takie rzutowania zawężające jak: Dim smallerData As Integer Dim largerData As Long = 3948 smallerData = largerData spowodują wygenerowanie błędów kompilacji (nawet jeśli faktycznie konwertowane dane mogą być bez trudu reprezentowane przez typy zmiennych docelowych). Oznacza to, że należy zasto- sować konwersję jawną (ang. explicit conversion): smallerData = CInt(largerData) 90 | Rozdział 4. Zmienne i typy danych
  • 33. Ustawiając wartość Off w opcji Option Strict, zezwalamy na stosowanie techniki konwersji niejawnej nawet wtedy, gdy może to prowadzić do występowania błędów w czasie wykony- wania programu. Oprócz wspomnianej opcji Option Strict, Visual Basic oferuje też wyrażenie Option Explicit, które również powinno być stosowane na początku plików z kodem źródłowym: Option Explicit {On | Off} Kiedy opcja Option Explicit jest włączona (On), wszystkie zmienne muszą być deklarowane (za pomocą słowa kluczowego Dim lub innego, podobnego) przed użyciem. Kiedy opcja Option Explicit jest wyłączona (Off), kompilator Visual Basica automatycznie doda (w czasie kompila- cji) niezbędne deklaracje dla wszystkich nazw napotkanych zmiennych, które nie zostały wcześniej zadeklarowane. (Nowe wyrażenia Dim nie zostaną umieszczone w naszym kodzie źródłowym — niezbędne deklaracje zostaną dodane „po cichu” w czasie kompilacji). Wyłą- czenie tej opcji może prowadzić do występowania w programie trudnych do zlokalizowania błędów. Więcej informacji na ten temat można znaleźć w podrozdziale „Wyrażenie Option Explicit” w rozdziale 12. Wartości domyślne obu opcji (Option Strict oraz Option Expli- cit) można ustawić we właściwościach projektu. Język Visual Basic zawiera funkcje konwertujące dla wszystkich podstawowych typów danych. Funkcja CBool Konwertuje dowolny prawidłowy łańcuch lub wyrażenie numeryczne na wartość typu Boolean. Kiedy wartość numeryczna jest konwertowana na wartość typu Boolean, wszyst- kie liczby różne od zera są zamieniane na True i tylko zero jest zamieniane na False. Funkcja CByte Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu- giwanego przez typ danych Byte) na wartość typu Byte, zaokrąglając ewentualną część ułamkową. Funkcja CChar Konwertuje pierwszy znak łańcucha na wartość typu danych Char. Funkcja CDate Konwertuje dowolną prawidłową reprezentację daty lub godziny na egzemplarz typu Date. Funkcja CDbl Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu- giwanego przez typ danych Double) na wartość typu Double. Funkcja CDec Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu- giwanego przez typ danych Decimal) na wartość typu Decimal. Funkcja CInt Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu- giwanego przez typ danych Integer) na wartość typu Integer, zaokrąglając ewentualną część ułamkową. Funkcja CLng Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu- giwanego przez typ danych Long) na wartość typu Long, zaokrąglając ewentualną część ułamkową. Typy danych | 91
  • 34. Funkcja CObj Konwertuje dowolne wyrażenie na egzemplarz typu Object. Takie rozwiązanie jest uza- sadnione w sytuacji, gdy chcemy, aby typ wartościowy był traktowany jak typ referen- cyjny. Funkcja CSByte Nowość w wersji 2005. Konwertuje dowolne wyrażenie numeryczne (którego wartość nale- ży do przedziału obsługiwanego przez typ danych SByte) na wartość typu SByte, zaokrą- glając ewentualną część ułamkową. Funkcja CShort Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu- giwanego przez typ danych Short) na wartość typu Short, zaokrąglając ewentualną część ułamkową. Funkcja CSng Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsłu- giwanego przez typ danych Single) na wartość typu Single. Funkcja CStr Konwertuje wyrażenie na jego reprezentację łańcuchową. Przykładowo, wartości typu Boole- an mogą być konwertowane na dwa łańcuchy: "True" lub "False". Daty są konwertowane na właściwe łańcuchy zgodnie z formatem zdefiniowanym w ramach ustawień regional- nych danego komputera. Funkcja CType Oferuje uniwersalny mechanizm rzutowania, za pomocą którego obiekt lub wyrażenie do- wolnego typu można przekształcać w odpowiednik innego typu. Funkcja CType może być stosowana dla wszystkich klas, struktur i interfejsów. Co więcej, okazuje się, że funkcja CType sprawdza się zarówno w przypadku podstawowych typów danych, jak i typów (w tym klas) definiowanych przez użytkownika. Poniżej przedstawiono składnię tej funkcji: CType(wyrażenie, nazwa-typu) Przykładowo, poniższe wyrażenie: Dim targetNumber As Integer = CType("12", Integer) jest odpowiednikiem następującego wyrażenia: Dim targetNumber As Integer = CInt("12") Nowość w wersji 2005. W wydaniu Visual Basica z 2005 roku dodano mechanizm przecią- żania operatorów, który szczegółowo omówimy w rozdziale 5. Jednym z elementów prze- ciążania operatorów jest możliwość definiowania reguł konwersji funkcji CType dla własnych, niestandardowych klas. Funkcja CUInteger Nowość w wersji 2005. Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsługiwanego przez typ danych UInteger) na wartość typu UInteger, zaokrąglając ewentualną część ułamkową. Funkcja CULong Nowość w wersji 2005. Konwertuje dowolne wyrażenie numeryczne (którego wartość należy do przedziału obsługiwanego przez typ danych ULong) na wartość typu ULong, zaokrąglając ewentualną część ułamkową. 92 | Rozdział 4. Zmienne i typy danych
  • 35. Funkcja CUShort Nowość w wersji 2005. Konwertuje dowolne wyrażenie numeryczne (którego wartość na- leży do przedziału obsługiwanego przez typ danych UShort) na wartość typu UShort, zaokrąglając ewentualną część ułamkową. Zmienne Zmienną (ang. variable) można zdefiniować jako konstrukcję posiadającą następujące własności: Nazwę Nazwa zmiennej jest wykorzystywana do jej identyfikowania w kodzie źródłowym. W języku programowania Visual Basic nazwa zmiennej musi się rozpoczynać albo od litery alfa- betu (odpowiedniego znaku Unicode), albo od znaku podkreślenia poprzedzającego kolejny znak podkreślenia lub dowolny znak Unicode (literę alfabetu, cyfrę, znak formatujący lub kombinację różnych znaków). Wraz z wprowadzeniem technologii .NET firma Microsoft zaproponowała nowy zbiór standardów nazewnictwa, które należy stosować w przypadku zmiennych i innych nazywanych obiektów. Wspomniane standardy omówiliśmy już w punk- cie „Konwencje nazewnicze” w rozdziale 1. Adres Każda zmienna ma przypisany adres pamięciowy, czyli miejsce składowania jej wartości. Zmienne stosowane w platformie .NET nie dają nam gwarancji, że reprezentowane dane będą stale składowane pod tymi samymi adresami, zatem same adresy zmiennych nie po- winny być rejestrowane ani wykorzystywane. Typ danych Typ danych zmiennej określa zakres możliwych wartości, które mogą być przez tę zmien- ną reprezentowane. Wartość Wartość zmiennej jest jej właściwą zawartością składowaną pod odpowiednim adresem pamięciowym. Wartość zmiennej określa się czasem mianem r-wartości (ang. r-value), ponieważ zawsze występuje po prawej stronie operatora przypisania. Przykładowo, poniż- sze wyrażenie: Dim targetValue As Integer = 5 można odczytać w następujący sposób: „Zapisz wartość 5 w pamięci, pod adresem repre- zentowanym przez zmienną targetValue”. Ponieważ nazwy zmiennej targetValue użyto na lewo od operatora przypisania, zmienna (lub jej lokalizacja w pamięci) bywa nazywana l-wartością (ang. l-value). Zakres Zakres zmiennej określa miejsca programu, w których dana zmienna będzie widoczna z perspektywy kodu źródłowego. Zakres zmiennych omówimy bardziej szczegółowo w dal- szej części tego rozdziału. Czas życia Od czasu życia zmiennej zależy to, kiedy i jak długo dana zmienna będzie istniała. Okazuje się, że zmienna może, ale nie musi być widoczna (należeć do bieżącego zakresu) w całym czasie życia. Także czas życia zmiennych zostanie szczegółowo przeanalizowany w dalszej części tego rozdziału. Zmienne | 93
  • 36. Deklaracja zmiennej Deklaracja zmiennej (ang. variable declaration) ma na celu związanie jej nazwy z określonym typem danych. W przypadku zmiennych nieobiektowych (typów wartościowych) deklaracja jest równoznaczna z utworzeniem egzemplarza danej zmiennej. Przykładowo, deklaracja w postaci: Dim createMeNow As Integer tworzy zmienną typu Integer nazwaną createMeNow. Powyższa deklaracja jest równoważna poniższemu wyrażeniu: Dim createMeNow As Integer = New Integer lub nawet wyrażeniu w postaci: Dim createMeNow As New Integer w którym położono nacisk na sam fakt tworzenia nowego egzemplarza obiektu zmiennej. Za pomocą pojedynczych wyrażeń można deklarować wiele zmiennych. Ogólnie, mimo że typ każdej z deklarowanych zmiennych może być inny, każdorazowe stosowanie nazw typów nie jest bezwzględnie wymagane. Jeśli w deklaracji zmiennej zrezygnujemy z jawnego określenia typu, wówczas zostanie zastosowany typ kolejnej zmiennej, dla której w sposób bezpośredni zadeklarowano właściwy typ. Przykładowo, poniższy wiersz kodu: Dim first As Long, second, third As Integer, fourth As String deklaruje między innymi zmienne second i third typu Integer (w Visual Basicu 6 second byłaby zmienną typu Variant). Visual Basic oferuje możliwość inicjalizacji zmiennych w wierszach ich deklarowania. (Przy- pisywana wartość bywa nazywana wartością inicjalizującą — ang. initializer). Przykładowo, poniższe wyrażenie: Dim alwaysInitialized As Integer = 5 deklaruje i tworzy zmienną typu Integer, po czym przypisuje jej wartość początkową równą 5. Okazuje się, że pojedyncze wyrażenia mogą zawierać także wiele operacji przypisania: Dim first As Integer = 6, second As Integer = 9 Warto pamiętać, że w przypadku stosowania wartości inicjalizujących dla każdej ze zmien- nych należy wprost określić typ danych. Zmienne obiektowe (zmienne typów referencyjnych) deklarujemy dokładnie tak samo jak ich odpowiedniki ze świata podstawowych typów danych: Dim newHire As Employee Przedstawiona deklaracja nie tworzy jednak zmiennej obiektowej — po wykonaniu tego wyra- żenia zmienna newHire będzie miała wartość Nothing. Utworzenie obiektu wymaga jawnego wywołania konstruktora odpowiedniej klasy na następujące sposoby: Dim newHire As New Employee lub: Dim newHire As Employee = New Employee lub nawet: Dim newHire As Employee newHire = New Employee 94 | Rozdział 4. Zmienne i typy danych
  • 37. Zakres, czas życia i poziom dostępu do zmiennych Każda zmienna ma swój zakres (ang. scope), który określa, w którym miejscu (lub miejscach) programu jej identyfikator jest właściwie rozpoznawany — gdzie w kodzie źródłowym dana zmienna jest widoczna. Zmienne lokalne: zakresy obejmujące blok kodu lub procedurę Wszystkie zmienne deklarowane wewnątrz funkcji, procedur bądź właściwości nazywamy zmiennymi lokalnymi (ang. local variables). Tego rodzaju zmienne mogą być wykorzystywane wyłącznie w ramach odpowiednich funkcji, procedur i właściwości — kiedy ich wykonywa- nie się zakończy, wszelkie zmienne lokalne związane z tymi konstrukcjami przestają istnieć (oczywiście jeśli nie zostały przekazane do innej zmiennej charakteryzującej się szerszym za- kresem). Ogólnie, zmienne lokalne charakteryzują się zakresem na poziomie procedury — są dostępne z poziomu wszystkich wierszy kodu wchodzących w skład odpowiedniej procedury. Dekla- racje zmiennych lokalnych z reguły występują na samym początku procedur lub funkcji (w kodzie wykonywanym bezpośrednio po wywołaniu tych konstrukcji): Public Sub DoTheWork( ) Dim localInt As Integer Dim localEmp As New Employee Bloki kodu są zbiorami wyrażeń zawartymi w ramach wyrażeń warunkowych If, w pętlach For, pętlach With i innych podobnych konstrukcjach języka programowania, dla których sto- suje się odrębne wyrażenia otwierające i zamykające. Wszystkie wyrażenia zdefiniowane pomiędzy wyrażeniami otwierającymi (If, ElseIf, For, With itp.) i zamykającymi (End If, Next, End With itp.) są częścią odpowiednich bloków kodu. Co więcej, zmienna zdefiniowana wewnątrz bloku kodu charakteryzuje się zakresem na poziomie bloku i jako taka jest widocz- na tylko w ramach tego bloku. Ponieważ bloki kodu mogą być zagnieżdżane, zmienne lokalne definiowane na poziomie tych bloków mogą występować dowolnie głęboko w hierarchii tego rodzaju zagnieżdżeń. Public Sub DoTheWork(ByVal fromWhen As Date, ByVal howMuch As Decimal) If (fromWhen < Today) Then ' ----- Ta zmienna jest dostępna tylko w skrajnie zewnętrznym bloku If, ' który dodatkowo zawiera skrajnie wewnętrzny blok If. Zmienna nie ' jest dostępna poza skrajnie zewnętrznym blokiem If. Dim simpleCalculation As Integer If (howMuch > 0@) Then ' ----- Ta zmienna jest dostępna tylko w skrajnie wewnętrznym ' bloku If. Dim complexCalculation As Integer End If End If End Sub Zmienne dostępne na poziomie bloków w ogóle nie są widoczne spoza bloków, w których zostały zdefiniowane. Przeanalizujmy teraz następujący blok kodu: If (origValue <> 0) Then Dim inverseValue As Decimal inverseValue = 1 / origValue End If ' ----- Poniższe wyrażenie zostanie odrzucone przez kompilator. MsgBox(CStr(inverseValue)) Zmienne | 95
  • 38. W powyższym kodzie zmienna inverseValue nie będzie rozpoznawana poza blokiem kodu, w którym została zdefiniowana, zatem ostatni wiersz przedstawionego kodu spowoduje błąd kompilacji. Wszystkie zmienne lokalne, niezależnie od tego, czy deklarujemy ja na poziomie bloków kodu, czy na poziomie procedur, charakteryzują się czasem życia równym czasowi życia swoich procedur (lub funkcji). Oznacza to, że zmienne deklarowane na poziomie bloków kodu zacho- wują swoje wartości przez cały czas życia procedury, która ten blok kodu zawiera (także w czasie wykonywania kodu spoza tego bloku). Przykładowo, w poniższym kodzie: Dim counter As Integer For counter = 1 To 5 If (ProcessData(counter) = True) Then Dim soFar1 As Integer Dim soFar2 As Integer = 0 soFar1 += 1 soFar2 += 1 MsgBox("Status na tym etapie: " & soFar1 & ", " & soFar2) End If Next counter zmienna soFar1 zachowuje swoją wartość z poprzedniego wykonania bloku If, w którym została zadeklarowana (z poprzedniej iteracji pętli For). W chwili wyświetlania pierwszego komunikatu wspomniana zmienna będzie zawierała wartość 1, w czasie wyświetlania drugiego komunikatu będzie zawierała wartość 2 itd. Ponieważ zmienną soFar2 zadeklarowano z warto- ścią inicjalizującą, wartość tej zmiennej będzie ponownie ustawiana (w tym przypadku zero- wana) w każdej kolejnej iteracji pętli For. Oznacza to, że wszystkie wyświetlane komunikaty będą zawierały wartość 1 na drugiej pozycji. Procedura może wykorzystywać zmienne przekazywane na jej wejściu za pośrednictwem argu- mentów. Zakres tego rodzaju zmiennych zawsze ogranicza się do poziomu danej procedury. Czas życia zmiennych lokalnych może wykraczać poza czas wykonywania procedury, w której te zmienne zadeklarowano. Przykładowo, zmienne statyczne (mimo lokalnego zakresu) „żyją” przez cały czas istnienia klasy lub modułu, do którego należą. Tego rodzaju zmienne należy deklarować ze słowem kluczowym Static (zamiast ze standardowym słowem kluczowym Dim): Static longLasting As Integer = 0 Wartość inicjalizująca zmiennej statycznej jest stosowana w momencie tworzenia egzempla- rza odpowiedniej klasy lub modułu (nie każdorazowo w chwili napotkania odpowiedniej deklaracji). Kiedy wchodzimy do procedury zawierającej jakąś zmienną statyczną, wspomniana zmienna będzie zawierała dokładnie tę samą wartość, którą zawierała podczas poprzedniego wykonywania danej procedury. Zmienne statyczne nie mogą być stosowane w procedurach składowych struktur. Zakres i poziomy dostępu w ramach modułów Wszystkie zmienne deklarowane wewnątrz klas (a także struktur i modułów), ale poza jakimi- kolwiek procedurami składowymi, charakteryzują się zakresem na poziomie typu i jako takie są dostępne z poziomu wszystkich procedur i funkcji wchodzących w skład tej samej klasy (lub struktury bądź modułu). Warto jednak pamiętać o możliwości prostego rozszerzania tego zakresu (poza poziom typu) za pomocą modyfikatorów dostępu (ang. access modifier). 96 | Rozdział 4. Zmienne i typy danych
  • 39. Dla każdej zmiennej deklarowanej na poziomie typu należy stosować słowo kluczowe mody- fikatora dostępu. (Równie dobrze można się posługiwać słowem kluczowym Dim, jednak wów- czas poziom dostępu będzie uzależniony od typów modułów, co może uczynić nasz kod nieczy- telnym). Modyfikatory dostępu przydzielają dostęp na poszczególnych poziomach stopniowo — modyfikator Poblic jest w tym względzie najmniej restrykcyjny (patrz tabela 4.1). Tabela 4.1. Modyfikatory dostępu Modyfikator dostępu Opis Public Zmienne publiczne są dostępne z poziomu dowolnego kodu, który ma dostęp do egzemplarza klasy bądź struktury lub do typu zawierającego te zmienne. Jeśli jakaś klasa zawiera zmienną publiczną i jeśli egzemplarz tej klasy jest dostępny z poziomu odrębnego projektu, aplikacji lub komponentu, także ta zmienna będzie dostępna z poziomu kodu klienckiego. Protected Zmienne chronione są dostępne zarówno w ramach klasy, w której zostały zadeklarowane, jak i z poziomu wszelkich klas potomnych względem tej klasy (ale nie spoza łańcucha klas związanych relacją dziedziczenia). Zmienne chronione mogą być deklarowane wyłącznie w klasach (nie można ich stosować w strukturach ani modułach). Friend Zmienne zaprzyjaźnione są dostępne z dowolnego miejsca w tym samym podzespole, ale nigdy spoza podzespołu — egzemplarze klasy zawierającej zmienne zaprzyjaźnione ukrywają te zmienne przed kodem zewnętrznym nawet wtedy, gdy same są przez ten kod wykorzystywane. Zmienne zaprzyjaźnione mogą być stosowane w klasach, strukturach i modułach. Protected Friend Stosowanie kombinacji słów kluczowych Protected i Friend powoduje, że tak deklarowane zmienne mają cechy zarówno zmiennych chronionych, jak i zmiennych zaprzyjaźnionych — są dostępne w ramach klasy i klas potomnych oraz w ramach tego samego podzespołu (ale nigdy poza tym podzespołem). Chronione zmienne zaprzyjaźnione mogą być stosowane wyłącznie w klasach (nie można ich stosować w strukturach ani modułach). Private Zmienne prywatne są dostępne z dowolnego punktu tej samej klasy, struktury lub modułu, ale nigdy poza swoją macierzystą konstrukcją. Zmienne prywatne są ukrywane nawet przed składowymi klas potomnych. Czas życia zmiennych deklarowanych na poziomie typów obejmuje cały czas życia egzem- plarza klasy, struktury lub modułu, do którego należą. Zmienne można deklarować jako dzielo- ne (ze słowem kluczowym Shared) i — tym samym — umożliwić istnienie odpowiednich wartości bez konieczności tworzenia egzemplarza klasy, struktury lub modułu. Warto jednak pamiętać, że czas życia zmiennych dzielonych rozciąga się na cały okres funkcjonowania aplika- cji. Wszystkie zmienne deklarowane w ciele modułu domyślnie są składowymi dzielonymi. Stałe Stałe (ang. constants) są w istocie zmiennymi dostępnymi tylko do odczytu. Raz ustawionej w kodzie programu wartości zmiennej (w czasie kompilacji) nie można zmieniać. Stałe są defi- niowane na poziomie lokalnym lub poziomie modułu za pomocą słowa kluczowego Const: modyfikatorDostępu Const nazwa As typ = wartość gdzie modyfikatorDostępu jest jednym z opisanych w poprzednim podrozdziale modyfika- torów dostępu. (Modyfikatory dostępu nie są stosowane w przypadku stałych deklarowanych wewnątrz procedur). Kiedy opcja Option Strinct jest włączona (ma wartość On), wszystkie stałe muszą być deklarowane z konkretnym typem. Stałe | 97
  • 40. Typy wyliczeniowe Typ wyliczeniowy (ang. enumeration) jest grupą wzajemnie powiązanych stałych całkowito- liczbowych. Wszystkie składowe wyliczenia muszą być nie tylko egzemplarzami tego samego typu danych, ale też typu całkowitoliczbowego (Byte, Integer, Long lub Short, a w wersji 2005 lub nowszej również SByte, UInteger, ULong lub UShort). Składowe typu wyliczeniowego są elementami dzielonymi i dostępnymi tylko do odczytu przez cały czas życia aplikacji. Public Enum VehicleType As Integer bicycle = 2 tricycle = 3 passengerCar = 4 eighteenWheeler = 18 End Enum Składowe typu wyliczeniowego można stosować w kodzie dokładnie tak jak stałe i zmienne: Dim whatIDrive As VehicleType whatIDrive = VehicleType.passengerCar Typy wyliczeniowe mogą być deklarowane wyłącznie na poziomie przestrzeni nazw lub modułu (w żadnym razie nie można ich deklarować wewnątrz procedur). Tablice Tablica w wielu językach programowania (włącznie z językiem Visual Basic) jest podstawową strukturą danych. Tablice umożliwiają składowanie kolekcji egzemplarzy podobnych typów danych lub obiektów. Każdy element znajduje się na pozycji oznaczonej unikatowym nume- rem. W Visual Basicu indeksy tablic rozpoczynają się od zera (zero jest dolną granicą) i kończą na zdefiniowanej górnej granicy. Poniższe przykłady ilustrują rozmaite sposoby deklarowania tablic jednowymiarowych: ' Konstruktor niejawny: Brak rozmiaru początkowego i wartości inicjalizujących. Dim days() As Integer ' Konstruktor jawny: Brak rozmiaru początkowego i wartości inicjalizujących. Dim days() As Integer = New Integer( ) {} ' Konstruktor niejawny: Obecność rozmiaru początkowego, brak wartości inicjalizujących. Dim days(6) As Integer ' Konstruktor jawny: Obecność rozmiaru początkowego, brak wartości inicjalizujących. Dim days() As Integer = New Integer(6) {} ' Konstruktor niejawny: Rozmiar początkowy wynikający z obecności wartości inicjalizujących. Dim days() As Integer = {1, 2, 3, 4, 5, 6, 7} ' Konstruktor jawny: Rozmiar początkowy i wartości inicjalizujące. Dim days() As Integer = New Integer(6) {1, 2, 3, 4, 5, 6, 7} Deklaracja tablicy może: • wywołać (w sposób jawny lub niejawny) konstruktor tablicy; • określić początkowy rozmiar wszystkich wymiarów tablicy lub pozostawić wszystkie roz- miary nieokreślone; • zainicjalizować elementy tablicy lub pozostawić ich wartości nieokreślone. 98 | Rozdział 4. Zmienne i typy danych
  • 41. W Visual Basicu 6 programista mógł określać zarówno dolne, jak i górne granice dla wszystkich wymiarów tablicy. W języku Visual Basic .NET dolną granicą (najniższym indeksem) wszystkich tablic jest zero. Przykładowo, wyrażenie w postaci: Dim myArray(5) As Integer deklaruje tablicę złożoną z sześciu elementów, gdzie indeks pierwszego będzie równy 0, a indeks ostatniego będzie równy 5. Tablice mogą się składać z wielu wymiarów (ang. dimensions). Przykładowo, poniższy wiersz deklaruje i inicjalizuje tablicę dwuwymiarową: Dim rectArray(,) As Integer = {{1, 2, 3}, {4, 5, 6}} Poniższy fragment kodu wyświetla zawartość tej tablicy: Debug.Write(rectArray(0, 0)) Debug.Write(rectArray(0, 1)) Debug.WriteLine(rectArray(0, 2)) Debug.Write(rectArray(1, 0)) Debug.Write(rectArray(1, 1)) Debug.WriteLine(rectArray(1, 2)) ' ----- Poniżej przedstawiono dane wyjściowe: 123 456 Górną granicę każdego z wymiarów tablicy można zmodyfikować za pomocą wyrażenia ReDim, którego ogólną składnię przedstawiono poniżej: ReDim [Preserve] nazwaTablicy(nowaGórnaGranica) Kwalifikator Preserve powoduje, że wszystkie wartości, które istnieją w momencie wykony- wania wyrażenia ReDim, zostaną zachowane w tablicy; w razie braku tego kwalifikatora cała tablica zostanie wyczyszczona. Jeśli zdecydujemy się użyć tego kwalifikatora, powinniśmy pamiętać, że modyfikacja górnej granicy może dotyczyć tylko ostatniego wymiaru tablicy. Liczba samych wymiarów tablicy nigdy nie może być zmieniana. Dolną i górną granicę danego wymiaru tablicy można określić odpowiednio za pomocą funkcji LBound oraz UBound: Dim smallArray(5) As Integer MsgBox(UBound(smallArray)) ' Wyświetla liczbę 5. Ponieważ dolną granicą wszystkich wymiarów tablicy jest indeks zerowy, funkcja LBound zawsze będzie zwracała właśnie zero. Kolekcje Visual Basic oferuje programiście obiekt tablicy asocjacyjnej nazwany kolekcją (ang. collection). Mimo wielu istotnych podobieństw do standardowych tablic, włącznie z występowaniem elementów w określonym porządku, warto pamiętać o tym, co odróżnia kolekcję od tablic: jej elementy mają postać par klucz-wartość. Elementy kolekcji można identyfikować zarówno według pozycji, jak i według klucza, lub stosując technikę iteracyjnego przeszukiwania kolej- nych pozycji. Szczególnie przydatna w codziennej pracy z kolekcjami okazuje się piątka składowych klasy Collection: Kolekcje | 99
  • 42. Metoda Add Dodaje element do kolekcji. Poza samymi danymi można określić opcjonalny klucz, za pośrednictwem którego będzie się można odwoływać do nowego elementu. Metoda Clear Usuwa wszystkie elementy z kolekcji. Właściwość Count Zwraca liczbę elementów składowanych w kolekcji. Właściwość Item Zwraca pojedynczy element składowany w kolekcji i identyfikowany albo według indeksu (pozycji w ramach kolekcji), albo według klucza (jeśli został określony w chwili dodawa- nia tego elementu do kolekcji). Metoda Remove Usuwa z kolekcji element na podstawie przekazanego indeksu bądź klucza. Poniższy fragment kodu definiuje kolekcję reprezentującą nazwy stanów identyfikowane za pomocą popularnych skrótów (w tym przypadku skróty występują w roli kluczy): Dim states As New Collection states.Add("New York", "NY") states.Add("Michigan", "MI") Elementy tej kolekcji można przeszukiwać iteracyjnie za pomocą prostej konstrukcji For Each...Next: Dim oneState As String For Each oneState In states MsgBox(oneState) Next oneState Podobnie jak w przypadku tablic, dostęp do elementów składowych kolekcji można uzyskiwać za pośrednictwem odpowiednich wartości indeksu. Dolna granica indeksu kolekcji zawsze wynosi jeden. Nowość w wersji 2005. W wersji języka Visual Basic wydanej w roku 2005 wprowadzono typy uniwersalne, które umożliwiają wiązanie egzemplarzy kolekcji (i innych klas) z konkretnymi typami danych w czasie wykonywania programu. Więcej informacji na ten temat można znaleźć w rozdziale 10. Parametry i argumenty Chociaż procedury są autonomicznymi blokami kodu, ich prawidłowe funkcjonowanie czę- sto wymaga interakcji z danymi spoza samych procedur. Dane zewnętrzne można przeka- zywać do procedur za pośrednictwem tzw. listy parametrów. Listę parametrów definiujemy w wierszu deklaracji procedury (w nawiasie, bezpośrednio za nazwą samej procedury): Public Function RepeatString(ByVal origText As String, _ ByVal howManyTimes As Integer) As String ' ----- Zwraca łańcuch wielokrotnie skonkatenowany z samym sobą. Dim counter As Integer RepeatString = "" For counter = 1 To howManyTimes RepeatString &= origText Next counter End Function 100 | Rozdział 4. Zmienne i typy danych
  • 43. Funkcja RepeatString otrzymuje na wejściu dwa parametry: origText oraz howManyTimes. Dla każdego parametru określono zarówno typ danych, jak i metodę przekazywania. Metoda przeka- zywania parametru to albo ByVal (przez wartość), albo ByRef (przez referencję). W technologii .NET domyślnym sposobem przekazywania parametrów jest przekazywanie przez wartość. Podczas wywoływania procedury pobierającej parametry przekazujemy na jej wejściu warto- ści, które na poziomie kodu wywołującego z reguły nazywa się argumentami. Przykładowo, poniższe wyrażenie dołącza dwa argumenty do wywołania funkcji RepeatString: łańcuch "abc" oraz liczbę całkowitą 5: targetString = RepeatString("abc", 5) Ponieważ w technologii .NET klasy mogą zawierać metody przeciążone, argumenty przekazy- wane przez nas na wejściu procedury muszą odpowiadać sygnaturze dokładnie jednej z prze- ciążonych wersji wywoływanej metody. Bardziej szczegółowe omówienie techniki przeciąża- nia można znaleźć w rozdziale 3. Przekazywanie argumentów Wszystkie argumenty są przekazywane albo przez wartość, albo przez referencję (w zależności od tego, czy przed nazwą odpowiedniego parametru użyjemy słowa kluczowego ByVal, czy ByRef). Kiedy dane są przekazywane przez wartość, docelowa procedura otrzymuje kopię wyrażenia lub zmiennej źródłowej. W samej procedurze parametr jest traktowany dokładnie tak jak zmienna lokalna — może być dowolnie wykorzystywany i modyfikowany, ale prze- staje istnieć w chwili zakończenia wykonywania procedury. Żadna ze zmian wartości parame- trów przekazanych przez wartość (zadeklarowanych ze słowem kluczowym ByVal) w ramach procedury nie będzie miała wpływu na wartość zmiennej źródłowej. Opisana zasada jest szcze- gólnie łatwa do weryfikacji w przypadku typów wartościowych. Przykładowo, przeanalizujmy teraz następujący fragment kodu: Public Sub ParentRoutine() Dim sourceValue As Integer = 5 ChildRoutine(sourceValue) MsgBox(sourceValue) ' --> Wyświetla 5 End Sub Public Sub ChildRoutine(ByVal incoming As Integer) incoming = 10 End Sub Chociaż wartość zmiennej sourceValue przekazanej do procedury ChildRoutine (za pośred- nictwem parametru incoming) została przez tę procedurę zmodyfikowana, odpowiednia zmiana nie została propagowana do kodu procedury wywołującej ParentRoutine, ponieważ para- metr incoming reprezentował kopię wartości zmiennej sourceValue. Z drugiej strony, obiekty (egzemplarze typów referencyjnych) przekazywane do procedur przez wartość mogą być przez te procedury modyfikowane. Precyzyjnie mówiąc, na poziomie pro- cedury można modyfikować składowe przekazanego obiektu, nie sam obiekt. W przypadku obiektów przekazywanych przez wartość w praktyce następuje przekazanie adresu pamięcio- wego, stąd zmiany dokonywane przez procedurę na danym obszarze pamięci znajdują odzwier- ciedlenie w oryginalnym obiekcie. Warto jednak pamiętać, że obiektu przekazanego przez wartość nie można na poziomie procedury zastąpić innym egzemplarzem tej samej klasy (nasze możliwości obejmują wyłącznie modyfikowanie składowych): Parametry i argumenty | 101
  • 44. Public Class DataClass Public DataMember As Integer End Class Public Class CodeClass Public Sub ParentRoutine() Dim sourceValue As New DataClass sourceValue.DataMember = 5 ChildRoutine(sourceValue) MsgBox(sourceValue.DataMember) ' --> Wyświetla 10 End Sub Public Sub ChildRoutine(ByVal incoming As DataClass) ' ----- Poniższy wiersz zmienia „rzeczywistą” składową. incoming.DataMember = 10 ' ----- Poniższe wiersze nie mają wpływu na zmienną sourceValue. incoming = New DataClass incoming.DataMember = 15 End Sub End Class Przekazywanie przez referencję (za pośrednictwem parametru zadeklarowanego ze słowem kluczowym ByRef) argumentu typu wartościowego na wejściu procedury zawsze oznacza przekazanie adresu pamięciowego odpowiedniej wartości — oznacza to, że ewentualne zmiany wprowadzone przez procedurę docelową będą miały bezpośredni wpływ na wartość odpowiedniej zmiennej źródłowej. (Ten mechanizm jest stosowany pod warunkiem, że wartość źródłowa jest składowana w zmiennej; stałe i wyrażenia obliczane w samym wywołaniu z natury rzeczy nie mogą być modyfikowane). Przykładowo, spróbujmy porównać poniższy kod ze słowem kluczowym ByRef z przedstawionym przed momentem odpowiednikiem zawie- rającym parametr przekazywany przez wartość: Public Sub ParentRoutine() Dim sourceValue As Integer = 5 ChildRoutine(sourceValue) MsgBox(sourceValue) ' --> Wyświetla 10 End Sub Public Sub ChildRoutine(ByRef incoming As Integer) incoming = 10 End Sub Jak widać, zastąpienie słowa kluczowego ByVal słowem ByRef miało istotny wpływ na funk- cjonowanie tego fragmentu kodu. W przypadku typów referencyjnych różnica nie jest tak widoczna, chyba że spróbujemy w procedurze docelowej całkowicie zastąpić oryginalny obiekt. Przekazywanie przez referencję daje taką możliwość! Wynika to z faktu, że słowo klu- czowe ByRef wymusza przekazywanie do procedury adresu adresu pamięciowego. Modyfi- kując ten adres pamięciowy, możemy w prosty sposób zastąpić adres reprezentowany przez zmienną źródłową. W niektórych językach programowania opisywany schemat jest nazywany podwójnym wskaźnikiem (ang. double pointer). Wszelkie wątpliwości związane z tym mecha- nizmem powinien wyjaśnić poniższy przykład. Warto porównać ten fragment kodu z podob- nym fragmentem, w którym zastosowano słowo kluczowe ByVal: Public Class DataClass Public DataMember As Integer End Class Public Class CodeClass Public Sub ParentRoutine( ) 102 | Rozdział 4. Zmienne i typy danych
  • 45. Dim sourceValue As New DataClass sourceValue.DataMember = 5 ChildRoutine(sourceValue) MsgBox(sourceValue.DataMember) ' --> Wyświetla 15 End Sub Public Sub ChildRoutine(ByRef incoming As DataClass) ' ----- Poniższy wiersz zmienia „rzeczywistą” składową. incoming.DataMember = 10 ' ----- Poniższe wiersze całkowicie zastępują egzemplarz wskazywany ' przez zmienną obiektową sourceValue. incoming = New DataClass incoming.DataMember = 15 End Sub End Class Stosowanie parametrów przekazywanych przez referencję łącznie z referencyjnymi typami danych umożliwia procedurom docelowym zastępowanie oryginalnych obiektów zupełnie nowymi egzemplarzami właściwych klas. Argumenty opcjonalne Język Visual Basic obsługuje parametry opcjonalne za pośrednictwem słowa kluczowego Optional: Sub Calculate(Optional ByVal silent As Boolean = False) W przypadku wszystkich parametrów opcjonalnych ma zastosowanie następująca para reguł: • Każda deklaracja argumentu opcjonalnego musi obejmować wartość domyślną, która do- datkowo musi mieć postać wyrażenia stałego (w żadnym razie nie może być zmienną). Wartość domyślna jest wykorzystywana tylko wtedy, gdy kod wywołujący nie dostarcza argumentu dla parametru opcjonalnego. • Każdy parametr zadeklarowany po parametrze opcjonalnym także musi być opcjonalny. Oznacza to, że ewentualne parametry obowiązkowe (nieopcjonalne) muszą się znajdo- wać na liście parametrów przed parametrami opcjonalnymi. W wersjach Visual Basica sprzed wprowadzenia technologii .NET istniała możliwość rezygnacji z wartości domyślnej i — jeśli typem parametru był Variant — stosowania funkcji IsMissing do określania, czy odpowiednia wartość została przekazana. Opisane rozwiązanie nie jest obsłu- giwane w platformie .NET, zatem dla wszystkich parametrów opcjonalnych koniecznie mu- simy definiować wartości domyślne (na wypadek braku odpowiednich argumentów). Tablice parametrów W normalnych warunkach definicja procedury określa stałą liczbę parametrów. Programiści Visual Basica mają jednak do dyspozycji słowo kluczowe ParamArray (od ang. parameter array — tablica parametrów), za pośrednictwem którego można rozszerzać listę parametrów poza stały zbiór elementów. Każde wywołanie tak zdefiniowanej procedury może zawierać inną liczbę parametrów (oczywiście oprócz puli parametrów wymaganych). Przeanalizujmy przykład funkcji wyznaczającej średnią ocenę z egzaminów, których liczba nie jest znana (liczba ocen wejściowych w każdym wywołaniu może być inna): Parametry i argumenty | 103
  • 46. Public Function AverageScore(ByVal ParamArray scores( ) _ As Single) As Single ' ----- Oblicza średnią ocenę dla dowolnej liczby egzaminów. Dim counter As Integer AverageScore = 0 For counter = 0 To UBound(scores) AverageScore += scores(counter) Next counter AverageScore /= UBound(scores) + 1 End Function Wywołania funkcji AverageScore mogą teraz zawierać zróżnicowaną liczbę argumentów: MsgBox(AverageScore(1, 2, 3, 4, 5)) ' --> Wyświetla 3 MsgBox(AverageScore(1, 2, 3)) ' --> Wyświetla 2 Poniżej przedstawiono reguły, które mają zastosowanie w przypadku parametrów deklarowa- nych ze słowem kluczowym ParamArray: • Procedura może otrzymywać na wejściu tylko jedną tablicę parametrów i ta tablica musi być ostatnim elementem na liście parametrów. • Tablica parametrów musi być przekazywana przez wartość, a jej deklaracja na liście para- metrów procedury zawsze musi być opatrywana słowem kluczowym ByVal. • Tablica parametrów musi być strukturą jednowymiarową. Jeśli nie zadeklarujemy jej typu, kompilator automatycznie założy, że tablica składa się z elementów typu System.Object. Tablica parametrów zawsze jest parametrem opcjonalnym. Jej domyślną wartością jest pusta tablica jednowymiarowa właściwego typu danych. 104 | Rozdział 4. Zmienne i typy danych