Etiketler
.Net - VB.net, Byval-ByRef, Makale, OOD, Püf Noktaları, Referans Tipler, String
“Byval – Byref ” in Değer ve Referans Tiplerdeki Davranış Farklılığı””Byval” ile “Byref” in farkını belli bir düzeye gelmiş her yazılımcı bilir. Zaten kısmen de adı üstündedir. Bir fonksiyona Byval ile değeri parametre olarak geçersiniz, dolayısıyla sadece değerini geçtiğiniz için orjinal değeriniz hiç bir zaman değişmez. Byref ile de değişkeninizin adresini parametre olarak geçersiniz, dolayısıyla da adresini geçtiğininiz için o değişkenin üzerinde gerçekleştiridiğiniz tüm işlemler aslında adresi üzerinden gerçekleştirildiği için orjinal değeri de doğal olarak değişir.Basit bir kaç örnek vereyim.
İlk örneğimizde değer tipli bir “integer” değeri fonksiyonlarımıza sırayla Byval ve Byref ile geçiyoruz ve değişimi inceliyoruz.
Dim valueType As IntegervalueType = 0Console.WriteLine(String.Format("Başanlagıç Değeri : {0}", valueType))
SubTakesValueTypeParametersWithByval(valueType)
Console.WriteLine(String.Format("Fonksiyona Byval ile parametre gönderildikten sonra : {0}", valueType))
FunctionTakesValueTypeParametersWithByref(valueType)
Console.WriteLine(String.Format("Fonksiyona Byref ile parametre gönderildikten sonra : {0}", valueType))
——
Public Sub SubTakesValueTypeParametersWithByval(ByVal valueType As Integer)
valueType = 1
End Sub
Public Sub FunctionTakesValueTypeParametersWithByref(ByRef valueType As Integer)
valueType = 2
End Sub
Birinci örneğimizde görüldüğü üzere, Byval ile parametre geçtiğimizde tanımladığımız değişkenin değeri değişmezken, Byref ile parametre geçtiğimizde değerinin değiştiğini gördük. Bu zaten Byval ve Byref in doğası gereği davranmasını beklediğimiz davranışıydı. Zaten bu bilinen bir davranıştır.İkinci örneğimizde referans tipli bir değişken olan bir sınıfı fonksiyonlara sırasıyla Byval ve Byref ile parametre olarak geçiyor ve değişimini inceliyoruz.
Public Class SimpleClassPrivate _valueType As Integer
Public Property ValueType() As Integer
Get
Return _valueType
End Get
Set(ByVal value As Integer)
_valueType = value
End Set
End PropertyEnd Class
Dim simpleClassForExampleOfReferenceTypes As New SimpleClass()
simpleClassForExampleOfReferenceTypes.ValueType = 0
With simpleClassForExampleOfReferenceTypes
Console.WriteLine(String.Format("Başanlagıç Değeri : {0}", .ValueType))
FunctionTakesReferenceTypeParametersWithByval(simpleClassForExampleOfReferenceTypes)
Console.WriteLine(String.Format("Fonksiyona Byval ile parametre gönderildikten sonra : {0}", .ValueType))
FunctionTakesReferenceTypeParametersWithByRef(simpleClassForExampleOfReferenceTypes)
Console.WriteLine(String.Format("Fonksiyona Byref ile parametre gönderildikten sonra : {0} ", valueType))
End With
———–
Public Sub FunctionTakesReferenceTypeParametersWithByval(ByVal referenceTypeClass As SimpleClass)
referenceTypeClass.ValueType = 1
End Sub
Public Sub FunctionTakesReferenceTypeParametersWithByRef(ByVal referenceTypeClass As SimpleClass)
referenceTypeClass.ValueType = 2
End Sub
İkinci örneğimiz, bu yazımızı yazma sebebimiz aslında. Çünkü Byval ‘ dan beklenmeyecek bir davranışa tanık olduk. Byval ile parametre olarak gönderdiğimizde değerinin değişmemesini beklerken değiştiğini gözlemledik. Peki bu nasıl oldu ? Niye oldu ?
Referans tipler byVal yada Byref ile parametre geçiliyor olmasından bağımsız olarak herzaman referansını üzerinden işlem görür.
Dolayısıyla fonksiyon içinde tabi tutuğunuz işlemler sırasında yeni bir değişken (ve adres) oluşturmaz. Mevcut adresi üzerinde çalışır ve tüm değişikleri taşır. ByVal in ByRef den tek farkı, ByVal ile parametre olarak geçerseniz, referansının bir kopyasını geçer, ByRef de ise kendi referansının adresi geçer. Fonksiyon içinde ByVal ile kopyasını geçtiğiniz referans tipli değişkene yeni bir adres atamazsanız, kopyasının referansı, orjinal kaydın referansını göstereceği için, orjinal kayıt değişikliklerden etkilenir.Çünkü çalışılan adres halen onun referansının adresidir. Fakat kopyasını geçtiğiniz değişkene sınıf içinde yeni bir değişken atarsanız (byvalIleGecilenDegisken = new YeniSinif), geçtiğiniz değişkenin adresi değişeceği, orjinal değişken bu değişimlerden etkilenmez.
Üçüncü örneğimiz ise “String” için olacak. Çünkü;
String “Değer tipli” ymiş gibi davranan “Referans Tipli” bir değişkendir.
Kendisine yaptığınız her atamada, bir örneğini daha yaratır. Bu zaten string in bilen dezavantajıdır. Yani hafızanızı şişirdikçe şişirir. Kaldıki bu yüzden derlerki String kullanmayın, Stringbuilder kullanın. Buda aslında kendisinin referans tipli olmasına rağmen değer tipli gibi hareket ettiğinin bir işaretidir. Örneğimize gelince, gördükki az önce referans tipli bir değişkeni Byval ile de Byref ile de parametre olarak geçsek değeri değişimlerden etkileniyor. Çünkü;
Referans tip değişkenler aslında herzaman refansı üzerinden işlem yaptırıyor.
Dim stringForExampleOfReferenceTypes As String
stringForExampleOfReferenceTypes = 0
Console.WriteLine(String.Format("Başanlagıç Değeri : {0}", stringForExampleOfReferenceTypes))
FunctionTakesStringParametersWithByval(stringForExampleOfReferenceTypes)
Console.WriteLine(String.Format("Fonksiyona Byval ile parametre gönderildikten sonra : {0}", stringForExampleOfReferenceTypes))
FunctionTakesStringParametersWithByRef(stringForExampleOfReferenceTypes)
Console.WriteLine(String.Format("Fonksiyona Byref ile parametre gönderildikten sonra : {0} ", stringForExampleOfReferenceTypes))
———–
Public Sub FunctionTakesStringParametersWithByval(ByVal stringParameter As String)
stringParameter = "1"
End Sub
Public Sub FunctionTakesStringParametersWithByRef(ByRef stringParameter As String)
stringParameter = "2"
End Sub
String’in özel durumunu ileride detaylı olarak tekrar ele alacağız. Umarım bu önemli püf noktası size faydalı olmuştur.
Örnek uygulamayı http://mehmetozakan.com/Download/Byval__Byref.rar indirebilirsiniz.