Makale Özeti

"VB.NET biliyorum C# da öğrenmek istiyorum." diyenler için bir makale dizisi.

Makale

VB.NET 'den C#'a - 3

Metod Parametreleri

VB.NET'de parametre tanımlamaları iki şekilde yapılırlar ByVal, ByRef. Parametrelerinin ayrımını sağlayan nokta, metoda parametre olarak verilen değerde yapılan değşikliklerin metodun çağrıldığı noktaya yansıyıp yansımayacağını belirlenmesidir.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim i As Integer

        i = 10

        metod1(i)

        MessageBox.Show(i)

    End Sub

    Public Sub metod1(ByVal i As Integer)

        i = 100

    End Sub

Yukarıdaki kod parçasının sonucunda ekranda mesaj kutusu ile 10 değeri görüntülenir.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim i As Integer

        i = 10

        metod1(i)

        MessageBox.Show(i)

    End Sub

    Public Sub metod1(ByRef i As Integer)

        i = 100

    End Sub

Yukarıda ki kod parçasında ise metod1 metodunun aldığı parametre ByRef olarak nitelendirildiği için metod1 metodu içinde yapılan değişiklikler çağrının yapıldığı değişkene yansır. Aslında altında yatan işleyiş ByRef olarak tanımlanan parametreye button1_click'deki i değişkenin adresi gönderilir, haliyle bu metotta yapılan değişiklik çağrının yapıldığı noktaya yansımaktadır.

Bu örneğimizde basit tür olarak tanımlanan integer veri türü kullanılmıştır. Bu durum reference type'lar içinde aynı mıdır? Tam olarak değil. İnceleyelim.

Public Class Makale

    Public Baslik As String

End Class

Yukarıdaki sınıfı aşağıdaki örneklerimizde kullanacağız.

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        Dim m As New Makale

        m.Baslik = "VB.NET bilenler için C# kılavuzu"

        metod1(m)

        MsgBox(m.Baslik)

    End Sub

    Private Sub metod1(ByVal mak As Makale)

        mak.Baslik = "yeni makale başlığı"

    End Sub

Yukarıda ki kod parçasında ilk örnekden farklı olarak parametre türü ByVal olsa bile parametre olarak gelen reference type'ın yani nesnenin Baslik alanı üzerinde yapılan değişik çağrı noktasına yansımıştır ve mesaj kutusunda yeni makale başlığı ifadesi gözükmektedir. Sebebi; reference type'ları gösteren değişkenler nesnenin kendisini değil adresini taşımaktadır. ByVal olarak bir kopyası aktarılan şey adresin kopyasıdır. mak değişkeni de Button2_click'deki m değişkeni de aynı nesneyi göstermektedir. Ancak aşağıdaki kod parçasında olduğu gibi metod1 metodu içerisinde m değişkeninin göstereceği yeni bir nesne oluşturulur ise m üzerinde yapılan değişiklikler beklendiği üzere çağrı noktasına yansımayacaktır. Zira m değişkeni artık yeni bir nesneyi göstermektedir.

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        Dim m As New Makale

        m.Baslik = "VB.NET bilenler için C# kılavuzu"

        metod1(m)

        MsgBox(m.Baslik)

    End Sub

    Private Sub metod1(ByVal mak As Makale)

        mak = New Makale

        mak.Baslik = "yeni makale başlığı"

    End Sub

Yukarıda ki örneği ByVal yerine ByRef ifadesi yazarak test edecek olursak mesaj kutusu ile yeni makale başlığı değeri görüntülenir.

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        Dim m As New Makale

        m.Baslik = "VB.NET bilenler için C# kılavuzu"

        metod1(m)

        MsgBox(m.Baslik)

    End Sub

    Private Sub metod1(ByRef mak As Makale)

        mak = New Makale

        mak.Baslik = "yeni makale başlığı"

    End Sub

Bu örnekte metod1 metodu içerisinde mak parametre değişkenine yeni bir nesne atansa da mak  parametresi ByRef olarak tanımlandığı için bu değişkene atanan yeni nesne çağrı noktasındaki değişkene de yansımaktadır.

Zira bir reference type'ı türünde olan bir değişken nesneyi taşımaz, nesnenin heap alandaki adresini taşır.Burada mak değişkeni m değişkenini, m değişkeni ise nesneyi göstermektedir.

ByVal ifadesi in, ByRef ifadesi ise inout anlamına gelmektedir. Yani ByVal ile parametre tek yönlü değer alabilir. ByRef ile ise parametre çift yönlü çalışabilir, değer alıp, aldığı değer üzerinde yaptığı değişiklikleri çağrı noktasına yansıtabilir.

C# dil kuralı olarak üç farklı durumu desteklemektedir.

ByVal karşılığı, olarak C#'da herhangi bir nitelendirici yazılmaz. C#'da nitelendirici tanımlanmadan yazılmış parametreler by-value olurlar.

        private void button1_Click(object sender, System.EventArgs e)

        {

            int sayi;

            sayi=10;

            metod1(sayi);

            MessageBox.Show(sayi.ToString());

        }

        public void metod1(int sayi)

        {

            sayi=100;

        }

Yukarıdaki kod parçası çalıştırıldığında mesaj kutusunda 10 değeri görüntülenecektir. Bu şekilde VB.NET'de ki ByVal nitelendiricisi ile aynı durumu elde ettik.

C#'da VB.NET'de ki ByRef yerine ref nitelendiricisi yer almaktadır.

        private void button1_Click(object sender, System.EventArgs e)

        {

            int sayi;

            sayi=10;

            metod1(ref sayi);

            MessageBox.Show(sayi.ToString());

        }

        public void metod1(ref int sayi)

        {

            sayi=100;

        }

Yukarıdaki örnek ile C#'da by-reference olarak parametre kullanımını görüyoruz. Metod tanımlamasıda parametre tanımlanırken ref ifadesi yazılır ve metod çağrısı yapılırken parametre olarak verilecek değeri taşıyan değişken önüne yine ref ifadesi eklenmelidir.

C#'da ref parametre verirken (ve birazdan göreceğimiz out) parametre değeri olarak sabit bir değer yazılamaz. yani ref 10 gibi bir ifade kullanılamaz. Ancak bir değişken tanımlanarak gerçekleştirilebilir. ref'in  kullanım senaryosuna bakıldığında bu zaten gerekli bir durumdur ancak VB.NET'de ByRef olan bir parametreye değer herhangi bir değişkene atanmadan verilebilmektedir.Tabi bu durumda by-reference olmasının bir işlevi kalmamaktadır.

Aşağıdaki C# örnek kod parçalarında aşağıdaki makale sınıfını kullanılacaktır.

    public class makale

    {

        public string baslik;

    }

VB.NET'de olduğu gibi C#'da da reference type'lar için durum biraz daha farklıdır.

        private void button2_Click(object sender, System.EventArgs e)

        {

            makale m=new makale();

            m.baslik="VB.NET bilenler için C# kılavuzu";

            metod1(m);

            MessageBox.Show(m.baslik);

        }

        private void metod1(makale mak)

        {

            mak.baslik="yeni makale başlığı";

        }

Yukarıdaki kod çalıştırıldığında tahmin edeceğiniz gibi mesaj kutusu ile yeni makale başlığı ifadesi görüntülenmektedir.

        private void button2_Click(object sender, System.EventArgs e)

        {

            makale m=new makale();

            m.baslik="VB.NET bilenler için C# kılavuzu";

            metod1(m);

            MessageBox.Show(m.baslik);

        }

        private void metod1(makale mak)

        {

            mak=new makale();

            mak.baslik="yeni makale başlığı";

        }

Yukarıdaki kod parçasında VB.NET'de olduğu gibi parametre türü bir reference type olsa da by-value olarak aktarılan mak adındaki parametreye yeni bir nesne atandığında mak değişkeni artık yeni bir nesneyi göstermektedir ve çağrı noktasındaki m değişkeni ile alakası kalmamıştır. Ancak metod1 içerisinde oluşturulan yeni nesnenin mak değişkenine atandığında çağrı noktasındaki m değişkenine de yansımasını istiyorsak metod1'in parametresini ref olarak tanımlamamız gerekmektedir.

        private void button2_Click(object sender, System.EventArgs e)

        {

            makale m=new makale();

            m.baslik="VB.NET bilenler için C# kılavuzu";

            metod1(ref m);

            MessageBox.Show(m.baslik);

        }

        private void metod1(ref makale mak)

        {

            mak=new makale();

            mak.baslik="yeni makale başlığı";

        }

Beklendiği gibi mesaj kutusunda yeni makale başlığı ifadesi görüntülenecektir. Zira oluşturulan ve mak değişkenine atanan yeni nesne mak değişkeninin by-reference gelmesi dolayısıyla çağrı noktasına da tanımlanmış olan m değişkenine de atanacaktır.

VB.NET dil yapısı tarafından desteklenmeyen ancak C#'da yer alan bir nitelendirici daha vardır. out ifadesi ile metot çağrıldıktan sonra değer dönüşü yapılır, ancak metod çağrısı yapılırken bir değer gönderilemez. Yani tek yönlü bir parametredir ve metottan dışarıya değer dönüşünü sağlar. out parametre olarak dönen değer yakalaması için metod çağrısında parametre olarak verilen değişken bir değer taşısa bile metoda bu aktarılmaz ve zaten metod içerisinde bu şekilde tanımlanmış bir parametre değişkeni kullanmak istendiğinz ilk değer verilmeden bir yerel değişkeni kullanamayacağımızı belirten bir derleyicisi hatası alırız.

        private void button3_Click(object sender, System.EventArgs e)

        {

            int iDonen;

            metod2(out iDonen);

            MessageBox.Show(iDonen.ToString());

        }

        private void metod2(out int sayi)

        {

            sayi=105;

        }

Yukardaki kod parçası ile ekranda gözüken mesaj kutusu 105 değerini gösterecektir. out parametre kullanımında aynı ref de olduğu gibi parametre tanımlanırken ve metod çağrısı yaparken gerekli nitelendirici ifade kullanılmalıdır, yani out.

out'un ref'den farkı sadece dönüş yolunun açık, geliş yolunun ise kapalı olmasıdır. Sadece geriye değer döner.

ParamArray kullanımı

VB.NET'de ParamArray ifadesi kullanılarak bir metoda aynı türde parametrelerin istendiği kadar verilebilmesini sağlarız.

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

        UrunleriSil(10, 11, 12)

        UrunleriSil()

        Dim urunler() As Integer = {13, 14}

        UrunleriSil(urunler)

    End Sub

    Private Sub UrunleriSil(ByVal ParamArray UrunID() As Integer)

        For Each id As Integer In UrunID

            'UrunID'si id olan ürünü sil

        Next

    End Sub

Örneğin yukarıdaki kod parçasında yer alan UrunleriSil metoduna istendiği kadar integer parametre verilebilir. Ve metodun buna göre işini yapması beklenir. UrunleriSil metodunu kullanana Button4_Click metodunda UrunleriSil metodu üç kere çağrılmıştır. Birincisinde üç parametre arka arkaya verilmiştir, ikincisinde hiç parametre verilmemiş, üçüncüsünde ise parametre olarak bir dizi verilmiştir.

ParamArray bir metodun sonuncu parametresi olmalıdır. ParamArray olarak tanımlanmış olan parametreye karşılık gelecek olan değerler virgül ile ayrılarak ardı ardına verildiğinde uygulama çalışırken bu değerleri içeren bir dizi değişken oluşturulup parametre olarak metoda verilir. Metod içerisinde ise parametre ismi bir dizi değişken olarak istenildiği şekide kullanılabilir.

C#'da ParamArray'e karşılık olarak params ifadesi vardır.

        private void button4_Click(object sender, System.EventArgs e)

        {

            UrunleriSil(10, 11, 12);

            UrunleriSil();

            int[] urunler={13,14};

            UrunleriSil(urunler);

        }

        private void UrunleriSil(params int[] UrunID)

        {

            foreach(int id in UrunID)

            {

                //UrunID'si id olan ürünü sil

            }

        }

Yukarıdaki kod parçasında UrunleriSil metodu yine üç kere çağrılmıştır. Arka arkaya verilmiş üç parametre ile, parametresiz ve bir dizi değişken verilerek. UrunleriSil metodu ise UrunID adındaki parametreyi dizi değişken olarak kullanmaktadır.

Exit Sub/Function/For/Do/While/Select

Exit Sub/Function gibi metottan istediğimiz anda çıkmak için kullandığımız metodların C#'da birebir karşılığı yoktur ancak VB.NET'de de yapılabildiği gibi C#'da return ifadesi ile metodan çıkılabilir.

Exit For/Do/While/Select ifadesi yerine ise C#'da break ifadesi kullanılır. Aşağıdaki kod parçası mesaj kutusu ile 10 değerini görüntüleyecektir.

                  int kova=0;

                  for (int i=0;i<200;i++)

                  {

                        kova += i;

                        if (kova==10) break;

                  }

                  MessageBox.Show(kova.ToString());

Ayrıca VB.NET'de olmayan (VB.NET 2005'de bu özellik geliyor) continue ifadesi ile for,while döngülerinin sonraki adımı ile devam edilmesi sağlanabilir.

                  int kova=0;

                  for (int i=0;i<200;i++)

                  {

                        kova += i;

                        if (kova==10) continue;

                  }

                  MessageBox.Show(kova.ToString());

Yukarıdaki kod parçasında daha önceki koddaki break ifadesi continue ile değiştirilmiştir. Bu kod parçasının çıktısı olarak açılan mesaj kutusunda 19900 yazacaktır.

 

Cengiz HAN
Microsoft ASP.NET MVP
cengiz@cengizhan.com