"Değişimler ve Geliştirmeler"

-----------------------------------------------------------------------------------------------------
Söz Diziminde Yapılan Değişiklikler

Visual Basic'i .NET'in ortak dil tanımlamasına uydurabilmek, eskimiş ve kullanılmayan özellikleri dilden atmak ve dili daha modern bir hale getirmek için söz diziminde değişiklikler yapılmıştır. Şimdi bunların neler olduğuna bakalım.
-----------------------------------------------------------------------------------------------------
Default Metotların ve Özelliklerin Kaldırılması

txtAdSoyad adındaki bir TextBox için VB6'da aşağıdaki gibi bir ifade geçerliydi :
Kod:
adiSoyadi = txtAdSoyad

Burada adiSoyadi değişkenine txtAdSoyad metin kutusunun Text değeri atanmaktadır. Yani metin kutuları için programcı tarafından aksi belirtilmediği takdirde varsayılan özellik Text özelliğidir. Yukarıdaki ifade daha anlaşılır olması için şu şekilde de yazılabilir :
Kod:
adiSoyadi = txtAdSoyad.Text

VB.NET için bu kullanımlardan ikincisi geçerli olduğu halde ilki geçerli değildir, çünkü artık varsayılan (default) metotlar ve özellikler kaldırılmıştır. Programcı neyi kullanmak istediğini tam olarak belirtmelidir.

Text özelliğine benzer şekilde Field özelliğinin kullanımında da tam yazım gerekmektedir. Value özelliği de artık Selection List'ler için varsayılan özellik olmaktan çıkmıştır. Aşağıda VB6'da geçerli kabul edilen bir yazım şekli görülmektedir :
Kod:
adiSoyadi = myRecordSet ("adSoyad")

Burada adiSoyadi değişkeninin içerisine myRecordSet adlı recordset objesinin adSoyad sahasındaki değer aktarılmaktadır. Bu kodun VB.NET'de çalışabilmesi için şu şekilde değiştirilmesi gerekir :
Kod:
adiSoyadi=myRecordSet.Fields("adSoyad").Value


-----------------------------------------------------------------------------------------------------
Set ve Let Gerektirmeyen Referanslar

Default metot ve özelliklerin kaldırılmasının sebebi obje referansları tanımlamada set ve let kullanımının önlenmesidir. Aşağıdaki söz dizimi VB6 ve öncesi için geçerlidir :
Kod:
Set txtYeniMusteri = txtEskiMusteri

Burada bir obje referansı ataması yapılmaktadır. Eğer Set kullanılmazsa obje referansı değil değer ataması (Text değerleri) yapıldığı varsayılır. Set ile derleyici bunun bir obje referansı olduğunu fark eder. Artık varsayılan özelliklerin kalkmış olmasından dolayı Set ve Let kullanımına da gerek kalmamıştır. Aşağıda VB.NET için geçerli olan bir obje referansı ataması görülmektedir :
Kod:
txtYeniMusteri = txtEskiMusteri

-----------------------------------------------------------------------------------------------------
Class Özelliklerindeki Söz Dizim Değişiklikleri

VB6 ve önceki iki sürümünde sınıf yapıları içerisinde Get, Let ve Set olmak üzere üç çeşit prosedür tanımlanabiliyordu. Bunlardan en az birinin olması şarttı. VB.NET'de Let prosedürü kaldırılmış, Get ve Set prosedürlerinin kullanım şekli değişmiştir. Let prosedürünün kaldırılmasının sebebi obje referansı ile değer atamaları arasındaki farkın default özelliklerin kaldırılması sonucu açıkça belli olması ve bu nedenle Let'e gerek kalmamasıdır. Aşağıda Get ve Set prosedürlerinin kullanımına ilişkin bir örnek görülmektedir :
Kod:
Private sifre as String Public Property sifrem As String Get sifrem = sifre End Get Set sifre = value End Set End Property

Get ve Set prosedürlerinin birlikte kullanılmasıyla programcının birinde bir değişiklik yapıp diğerini unutması engellenmiştir. Ayrıca Get ve Set prosedürlerinin birlikte kullanılması gerekmektedir. Get'i kullanıp Set'i kullanmamak (sadece okunur) ya da Set'i kullanıp Get'i kullanmamak (sadece yazılır) için Property tanımlamasında ReadOnly ya da WriteOnly olarak belirtmek gerekir. Aşağıda ReadOnly ve WriteOnly özellikler için örnekler gösterilmiştir :
Kod:
Private sifre as String Public ReadOnly Property sifrem As String Get sifrem = sifre End Get End Property Public Property sifrem As StringSet sifre = value End Set End Property

-----------------------------------------------------------------------------------------------------
Parantez Kullanma Zorunluluğu

VB.NET hiçbir argüman belirtilmese dahi parantez kullanımını gerektirmektedir. Örneğin aşağıdaki kod VB'in eski versiyonları için geçerlidir :
Kod:
MsgBox "Selam, Millet"

Bu kodun VB.NET için geçerli olabilmesi için parantez kullanılması gerekmektedir :
Kod:
MsgBox("Selam", MsgBoxStyle.Critical, "Millet")

Burada MsgBoxStyle.Critical ile ekrana kritik bir mesaj yazdırılacağı belirtilmektedir.

Parametreler Varsayılan Olarak ByVal'dır

VB6 ve önceki sürümlerde bir argüman listesindeki elemanlar daima varsayılan bir özelliğe sahiptiler. Fakat bu varsayılan değer integer, string ve boolean gibi asıl veri tipleri için ByRef oluyor iken, object gibi asıl veri tiplerinin dışındaki veri tipleri için ByVal olmaktaydı. Programcı asıl veri tiplerini kullanıyor iken ByVal olarak kendisi bir bildirimde bulunmadıysa program derlenirken hiçbir hata olmamasına rağmen programın çalışması sırasında sebebinin bulunması zor olabilen hatalarla karşılaşılabilyordu. ByRef olarak yapılan tanımlamalarda bir rutine verilen parametrelerdeki değişim rutinin dışına da yansımaktadır. VB.NET bu sorunu giderebilmek için programcı tarafından belirtilmediği sürece paramtreleri varsayılan olarak ByVal kabul eder.
-----------------------------------------------------------------------------------------------------
Yeni Tanımlama Şekilleri

Visual Basic'in değişken tanımlamalarında bazı gariplikler vardı fakat bu gariplikler VB.NET'de çözülmüştür. VB6'da farklı veri tipindeki değişkenlerin tek bir satırda tanımlanmasına izin veriliyordu. Örneğin Kod:
Dim baslik As String, sayac As Integer

Yukarıdaki kod VB.NET'de çalışmayacaktır. Çünkü VB.NET tek bir satırda sadece aynı veri tipine ait değişkenlerin tanımlanmasına izin vermektedir. Örneğin ;
Kod:
Dim baslik , adSoyad As String

Yukarıdaki kod VB6'da farklı bir şekilde çalışacaktır. baslik değişkeni Variant olarak kabul edilecektir. VB.NET'de her ikisi de String kabul edilir. Değişkenlere tanımlama sırasında ilk değerler verilebilir :
Kod:
Dim yas As Integer = 22 Dim adi As String = "Tarık Özkan" Dim ikramiye As Integer = birimucret * 30

-----------------------------------------------------------------------------------------------------
Dizi Tanımlamalarındaki Değişim

Tüm diziler sıfır tabanlıdır ve tanımlama sırasında kullanılan sayı gerçek uzunluğu verir. Aşağıda bir VB6 kodu verilmiştir :
Kod:
Dim musteriler(50) As String

Bu kod aslında 51 elemanlı bir dizi oluşturur. İlk musteri sıfır numaralı olan ve son musteri de ellinci olacak şekildedir. Visual Basic.NET'de durum farklıdır. Dizinin uzunluğu tanımlamadaki gibi 50'dir. İlk elemanı sıfırıncı ve son elemanı kırk dokuzuncudur. Musteriler(50)'ye yapılacak bir referans out-of-bounds hatasının çıkmasına sebep olacaktır.

Biz bu kitabı yazarken beta sürümleri kullandık. Eğer gerçek versiyonda da dizi tanımlamaları ve kullanımı bu şekilde olursa eski Visual Basic kodlarını .NET'e çevirirken hatalar çıkacaktır. Ayrıca VB kullanıcıları 1 tabanlı dizileri kullanmaya alışık oldukları için yeni duruma alışana kadar hata yapmaları normaldir.

Değişken tanımlamalarında olduğu gibi dizilerde de tanımlama sırasında ilk değerlerin verilmesi mümkündür. Örneğin aşağıdaki dizi tanımlamasında dizinin tüm değerleri tanımlama sırasında verilmektedir :
Kod:
Dim oyuncular(4) As String = ( "Necati" , " Kezban" , "Zekeriya" , "Mahmut" )

Oyuncular dizisinin elemanlarına referans tanımlarken oyuncular(0) ... oyuncular(3) şeklinde olmalıdır.

Dizi tanımlamalarında boş indeks kullanıp daha sonra redim ile kapasiteyi arttırma ortadan kaldırılmıştır. Diziler daima Dim ile tanımlanmalıdır. Redim sadece dizinin uzunluğunu değiştirmek için kullanılabilir.
-----------------------------------------------------------------------------------------------------
Formların Yüklenmesi

Visual Basic formları kendilerine ilk referans tanımlandığında yükleniyorlardı. Visual Basic.NET'de formun yüklenmesi için programcı tarafından bildirilmesi gerekmektedir. Aynen diğer objelerde olduğu gibi. Bir form modülünün de aslında normal bir sınıf olduğundan, farkının sadece formlara ait yetenekleri olması olduğundan önceki konularda bahsetmiştik. Bu kısa hatırlatmanın ışığı altında aşağıdaki koda baktığımızda bir formun aynen diğer objeler gibi yaratıldığını ve gösterildiğini görebiliriz:
Kod:
Dim yeniForm As New Form3() yeniForm.Show()

Burada Form3 adında bir formun proje içersinde önceden yaratılmış olduğu varsayılmıştır. Bu kodun VB6'dan farkı parantezlerin kullanılmış olmasıdır.
-----------------------------------------------------------------------------------------------------
Bit İşlemleri

VB6'da bit operatörleri (And, Or, Xor ve Not) hem boolean hem de aritmetik işlemler için kullanılıyordu. Aşağıdaki VB6 kodlarından ilki bit bazında aritmetik, ikincisi ise boolean işlem yapmaktadır :
Kod:
Dim ilkDeger As Integer Dim ikinciDeger As Integer ilkDeger = &H1E ' decimal karşığı 30 ikinciDeger = &H32 ' decimal karşığı 50 MsgBox (ilkDeger And ikinciDeger) 'ekrana 16 yazar
Kod:
Dim baslik As String = "yoo" Dim adi As String = "eren" If (Len(baslik) = 3) And (Len(adi) = 4) Then MessageBox.Show("eşitlik sağlandı") End If

İlk messagebox ekrana 16 yazdıracaktır, çünkü 1E ve 32'nin AND'lenmesi sonucunun decimal karşılığı 16'dır. İkinci messagebox ekrana "eşitlik sağlandı" yazısını getirecektir, çünkü AND'in solundaki ve sağındaki karşılaştırmaların sonuçları doğrudur yani 1'dir.
Değişkenlerin Tanımlı Oldukları Alanlardaki Değişim

Visual Basic 6.0'da değişkenler prosedür içinde herhangi bir yerde tanımlanabilir ve prosedürün tamamında geçerlidir. Eğer değişken bir blok içinde tanımlanırsa bloğun dışında da değişkenin içerdiği değere erişilebilir. Örneğin bir loop, for ve if bloğu gibi. Aşağıda VB6'da yazılmış bir kod görülmektedir :
Kod:
Do Dim sayac As Integer sayac = sayac + 1 Loop While sayac<100 MsgBox sayac

Bu kod VB6'da çalışacak ve ekrana 100 mesajını verecektir. Yani sayac değişkeni loop içinde tanımlı olduğu halde loop dışından da erişilebilir durumdadır.

Visual Basic.NET'de durum farklıdır. Bir blok içinde tanımlı olan bir değişken sadece o blok içerisinden erişilebilir durumdadır. Yukarıdaki kodun VB.NET'de çalışıp ekrana 100 mesajını yazdırabilmesi için şu şekilde değiştirilmesi gerekir :
Kod:
Dim sayac As Integer Do sayac = sayac + 1 Loop While sayac<100 MsgBox(sayac)

Bir blok içinde tanımlanan bir değişken blok dışına çıkıldığında içerdiği değeri kaybetmez. Bloğa tekrar girilse dahi değer hala kaybolmamıştır. Değişken içerdiği değeri blok dışına çıkıldığında kaybetmese de blok dışından o değişkene referans tanımlanamaz.
Kullanımına Son Verilen Anahtar Kelimeler

Aşağıdaki anahtar kelimelerin kullanımına son verilmiştir ve bundan sonra kullanılmayacaklardır :

• • Let
• • Gosub
• • Option Base 0 | 1
• • On x Goto
• • VarPtr, ObjPtr, StrPtr
• • DefLng, DefCur, DefBool, DefByte, DefSng, DefObj, DefVar, DefDbl, DefDec, DefDate, DefStr

Eski Visual Basic kodlarını .NET'e geçirirken bu anahtar kelimelerin geçtiği yerlerin düzeltilmesi gerekecektir.
-----------------------------------------------------------------------------------------------------
Hataları Yönetmek
Bu makalede Visual Basic ortamına VB.NET ile birlikte yeni gelen bir özellik olan Try-Catch-Finally metodunu inceleyeceğiz.



Try-Catch-Finally, daha önceden C++ ve Java programcılarının kullandığı, hataları denetim altına almayı oldukça kolaylaştıran bir yapı.
Kullanımı:
Kod:
Try 'Hatanın oluşabileceği kod bloğu Catch 'Hata meydana geldiğinde uygulanacak kod bloğu Finally 'Her durumda çalışan kod bloğu End Try ' Denetimi bitir

Try ve End Try'ı kullanmak zorunlu, Catch ve Finally isteğe bağlı olarak kullanılabilir. (If-end if deyimine benzer bir kullanım yapısı var.)
Bir örnekle nasıl kullanıldığını görelim: Bir console application açalım ve main prosedürünün içine
Kod:
Dim x As Integer = 15 Dim y As String = "beş" Dim z As Integer = x / y

yazalım. Birinci satırda tipini integer olarak belirttiğimiz x değişkenine integer bir değer olan 15 sayısını, ikinci satıra ise tipini string olarak belirttiğimiz y değerine string bir değer olan "beş" değerini atadık. Üçüncü satırda programımız integer değeri olan x'i, string bir değeri olan y'ye bölmeye çalışacak; bu işlem mümkün olmadığından doğal olarak hata verecek ve program orada sonlanacaktır.
Şimdi de aynı ifadeye Catch'i ekleyelim.
Kod:
Try Dim x As Integer = 15 Dim y As String = "beş" Dim z As Integer = x / y Catch Console.Writeline("Bir Hata Oluştu") End Try

Kodu çalıştırdığınızda programın bir önceki örnekte karşılaştığımız hatayı vermediğini ve "Bir Hata Oluştu" uyarısının ekranda göründüğünü göreceksiniz. Peki bu nasıl oldu da oldu?
Hata çıkması muhtemel olan kod bloğunu Try – End Try arasına alıyoruz. Bu aralıkta bulunan kod bloğunda herhangi bir hata durumu oluştuğunda program hata vermeden ve programı sonlandırmadan doğrudan Catch'e gidiyor ve bu blok arasında yer alan kodu uygulamaya geçiyor. Yazdığımız koda geri dönersek Try'dan sonraki kod bloğunda yukarıda bahsettiğimiz hata durumu oluştu ve bir öncekinin aksine program hatası vermeden doğrudan Catch de kod bloğundaki koda geçti ve o kodu uygulayarak ekrana "Bir Hata Oluştu" yazdırdı.
Şimdi de Try-Catch-Finally ifadesinde yine opsiyonel ifadelerden biri olan Finally'nin nasıl kullanıldığını görelim. Finally kod bloğunda bulunan kod her durumda çalıştırılacaktır.
Kod:
Try Dim x As Integer = 15 Dim y As String = "beş" Dim z As Integer = x / y Catch Console.Writeline("Bir Hata Oluştu") FinallyConsole.Writeline("Bu yazı her durumda görüntülenecektir.") End Try

Programı çalıştırdığınızda bir önceki örneğe ilave olarak ekranda "Bu yazı her durumda görüntülenecektir." yazısı görüntülenecektir.

Catch'e tekrar geri dönersek çıkan hataların ne tür bir hata olduğunu tespit edebilmekte mümkün.
Kod:
Catch a As Exception Console.WriteLine("Bir Hata Oluştu:" & a.ToString())

Burada Exception tipindeki hatayı a değişkenine atadık ve toString() metoduyla hatanın açıklamasını alıp ekrana yazdırdık.
toString(): Hatanın açıklamasını verir.
Source: Hataya neden olan uygulama ya da objenin adını verir.
StackTrace: Hatanın oluştuğu stack'i verir.
Ayrıca farklı hata durumlarına göre farklı catch blokları açabilir ve buradaki kodları devreye sokabiliriz.
Kod:
Catch a As InvalidCastException Console.Writeline("Geçersiz karşılaştırma işlemi") Catch a As Exception Console.WriteLine("Bir Hata Oluştu:" & a.ToString())

Örnekte mevcut hatamızın tipi InvalidCastException olduğu için program o catch bloğunu çalıştıracaktır. ,
Gördüğünüz gibi Try-Catch-Finally, hataları yakalama ve kontrol etme (error handling) konusunda işimizi oldukça kolaylaştıran bir yöntem.