• Anasayfa
  • Hakkımızda
  • Etkinlikler
  • Destek Verin
  • Site Haritası
  • Giriş Yap
  • Üye Ol
  • Facebook
  • Twitter
  • RSS
Yazılım Dilleri
  • Soru - Cevap
  • EĞİTİM SETİ
  • KATEGORİ
  • DUYURU
  • TEKNOLOJİ HABERLERİ

Son Sorular

  • 8/2/2020 11:38:31 PM'Basit' Yazılım Dili
  • 6/25/2020 3:18:13 PMderleme hatası
  • 12/11/2017 4:49:15 PMWindows Hizmeti Hk.
  • 4/23/2016 12:55:33 AMC programlama 2 oyun

Popüler Sorular

  • 5/27/2012 5:49:50 AMAsp.Net ile Date time alana veri ekleyemiiyorum ?
  • 4/2/2012 12:45:18 AM.exe uzantılı dosya için dijital imza nerde nasıl alınır.
  • 5/12/2012 8:44:49 AMAcil Yardım
  • 5/27/2012 1:46:51 PMveri tabanı bağlantısı
  • .Net Framework
  • 8085 Assembly
  • Active Directory
  • ADO.NET
  • Android
  • Apple IOS
  • Arduino
  • ASP.NET
  • ASP.NET MVC
  • Blackberry
  • C#.Net
  • C++
  • CCG Framework
  • CISCO
  • CSS
  • Diğer
  • Dreamweaver
  • Entity Framework
  • Exchange Server
  • Gömülü Sistemler
  • GSM Programlama
  • Güncel
  • Güvenlik
  • HTML5
  • Java
  • Javascript / JQuery
  • Jira
  • Kariyer ve İş Yaşamı
  • LibreOffice
  • LINQ
  • Linux
  • Matlab
  • Microsoft Dynamics CRM
  • Mobil Uygulama Geliştirme
  • MySQL
  • NoSQL
  • Oracle
  • OWIN
  • PFSense
  • PHP
  • Powershell
  • Python
  • Sanallastirma
  • SAP-ABAP
  • SCOM 2012
  • SEO
  • Sharepoint 2010
  • Sharepoint 2013
  • Silverlight
  • Sistem Analiz ve Tasarımı
  • SQL Server
  • Symantec
  • TFS
  • T-SQL
  • Ubuntu
  • VB.NET
  • Veritabanı Yönetim Sistemleri
  • Visual Studio
  • VMware
  • WCF
  • Web Hosting
  • Windows 8
  • Windows Azure
  • Windows Phone 7.1
  • Windows Phone 8
  • Windows Server
  • Wordpress
  • WPF
  • Xamarin
  • XNA
  • Yazılım Mühendisliği
  • Yöneylem Araştırması
  • ASP.NET MVC
  • Entity Framework
  • Javascript / JQuery
  • LINQ
  • PHP

Son Duyurular

IPhone 6 ve IPhone 6 Plus Teknik Özellikleri ve Fiyatı

IPhone 6 ve IPhone 6 Plus Teknik Özellikleri ve Fiyatı

DELL'in Yeni Projesi: USB Bilgisayar (Project Ophelia)

DELL'in Yeni Projesi: USB Bilgisayar (Project Ophelia)

Windows Phone Youtube Uygulaması Google ve Microsoft ile Yeniden Yapılıyor

Windows Phone Youtube Uygulaması Google ve Microsoft ile Yeniden Yapılıyor

Android ve Apple IOS Telefonlar için Blackberry Messenger (BBM)

Android ve Apple IOS Telefonlar için Blackberry Messenger (BBM)

Nokia Lumia 925 Teknik Özellikleri, Lumia 928 ve 920 ile Karşılaştırması

Nokia Lumia 925 Teknik Özellikleri, Lumia 928 ve 920 ile Karşılaştırması

LG Optimus G Pro Özellikleri ve Gözle Video Oynatma Teknolojisi

LG Optimus G Pro Özellikleri ve Gözle Video Oynatma Teknolojisi

Sıfır Sabit Değeri ve Enum Sorunu

.Net' in temel tiplerinden birisi olan Enum sabitleri ile sıfır sabit değeri arasındaki ilişkili inceliyoruz.

03.10.2013

Yazar: Burak Selim Şenyurt (Google+)

Kategori: C#.Net

4606

C# konulu yeni bir bilmece ile karşı karşıyayız. Bu sefer kolay kolay fark edemeyebileceğimiz, basit ama irdelenmesi gereken bir vakayı göz önüne alacağız.

Bir uygulamayı geliştirirken, Developer olarak son derece dikkatli olmalı ve testlerimizi gerçekleştirirken de tüm senaryoları göz önüne almalıyız. Bu anlamda gerek dilin gerek.Net Framework alt yapısının tüm unsurlarına hakim olmak da son derece önemli.

Nitekim bazı noktalarda profesyonel bir geliştiricinin dahi kestiremeyeceği sorunsallar yaşanabiliyor. Yazımızın ilerleyen kısımlarında bu perspektiften bakarak sorun olarak da görülebilecek bir konuyu masaya yatıracağız.

Senaryo

İlk olarak C# dili ile geliştireceğimiz aşağıdaki basit kod parçasını göz önüne alalım.

using System; 
using System.Collections.Generic;

namespace EnumAndZeroConstant 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            List<Information> infos = new List<Information>() 
                                          { 
                                              new Information("Hata mesajı"), 
                                              new Information(InformationType.Application), 
                                                              new Information(InformationType.Member), 
                                                              new Information(InformationType.System), 
                                                              new Information(0), 
                                                              new Information(1), 
                                                              new Information(2), 
                                                              new Information(3) 
                                          };

            foreach (Information info in infos) 
            { 
                Console.WriteLine(info.SummaryMessage); 
            }

        } 
    }

    enum InformationType 
    { 
        System, 
        Application, 
        Member 
    }

    class Information 
    { 
        public string SummaryMessage { get; private set; }

        public Information(object commonInformation) 
        { 
            SummaryMessage = commonInformation.ToString(); 
        }

        public Information(InformationType informationType) 
        { 
            switch (informationType) 
            { 
                case InformationType.Application: 
                    SummaryMessage = "Uygulama bilgisi"; 
                    break; 
                case InformationType.System: 
                    SummaryMessage = "Sistem bilgisi"; 
                    break; 
                case InformationType.Member: 
                    SummaryMessage = "Üyeden"; 
                    break; 
                default: 
                    SummaryMessage = "Bilinmeyen kaynak"; 
                    break; 
            } 
        } 
    } 
}

Uygulamamızda InformationType isimli bir Enum sabiti ve bu tipi kullanan Information isimli bir sınıf(Class) tanımlanmıştır. Information sınıfı içerisinde yer alan SummaryMessage isimliözelliğimiz(Property) dikkat edileceği üzere Read Only belirtilmiştir(set keyword’ ü başındaki private kullanımına dikkat)

Information sınıfı içerisinde kullanılan SummaryMessage özelliğinin değerini set etmek için,yapıcı metod(Constructor) parametrelerinden yararlanılmaktadır. İki adet aşırı yüklenmiş yapıcı metod(Overload Contstructor) mevcuttur. Bunlardan birisi InfortmationType enumsabiti tipinden bir değişken almakta ve bunun değerine göre SummaryMessage özelliğine stringbir değer atamaktadır. Bu anlamda diğer aşırı yüklenmiş versiyon ise, object tipinden gelen referans değişkenin, ToString metodunun sonucunu kullanmaktadır.

Main metodu içerisinde test amaçlı olaraktan, Information tipinden generic bir List koleksiyonu değerlendirilmektedir. Dikkat edileceği üzere, koleksiyonun Information tipinden olan her bir nesne örneği üretilirken, parametre olarak farklı referanslar gönderilmektedir. Test amacıyla String, int, InfortmationType türünden değişken değerleri ele alınmaktadır.

“Peki bu kod parçasında nasıl bir tuzak olabilir? Ya da başka bir deyişle bir tuzak var mıdır? Gözümüzden kaçırdığımız bir nokta söz konusu ise nedir? “

Düşünsel ve Gerçek Çalışma Sonuçları

Bu sorulara cevap bulabilmek için öncelikli olarak kodun nasıl bir sonuç üreteceğini düşünmeye çalışalım. Aslında beklentimiz, uygulamanın çıktısının aşağıdaki temsilde olduğu gibi üretilmesidir.

Hata mesajı 
Uygulama bilgisi 
Üyeden 
Sistem bilgisi 
0 
1 
2 
3

Ancak, yapıcı metoda gönderilen 0 değerinden pis kokular gelmektedir. Ne demek istediğimi daha net bir şekilde ifade edebilmek için uygulamanın çalışma zamanı(Runtime) ekran çıktısına bir bakalım dilerseniz.

 

Uppsss! Bir fark görebildiniz mi? Biz yapıcı metodumuza 0 değişkenini göndermemize rağmen, ekrana InformationSystem enum sabitindeki ilk değere karşılık gelen string mesajı döndürülmüştür. Gerçekten de uygulamayı debug ettiğimizde, 0 değerini yapıcı metoda gönderdikten sonra Enum sabitini parametre olarak kullanan versiyonuna gittiğimizi görürüz. Kodu biraz değiştirip Debug işlemimizi icra edelim ve bu durumu çalışma zamanında görelim.

infoZero isimli Information tipinden olan değişken örneklenirken, yapıcı metoda 0 integer değeri gönderilmiştir. Ancak kod bu satırdan sonra object tipinden parametre alan versiyon yerineInformationType tipinden referans kullanan yapıcı metoda sıçramıştır. Üstelik 0 integer değer,bilinçsiz bir şekilde(Implicitly) InfortmationType.System sabit değerine dönüştürülmüştür.

Tabi bizim buradaki asıl beklentimiz 0 gibi bir sayısalın object gibi algılanması ve uygun olan yapıcı metoda gitmesi yönündedir. Ne varki bu gerçekleşmemiştir. Bu aslında 0 sayısal değerinin bilinçsiz olarak bir Enum sabiti formunda algılanıyor olmasıdır. Yani sıfır tabanlı sabit olarak algınanan yapıcı metod parametresi, bilinçsiz olarak Enum karşılığına dönüştürülmüştür.

IL Tarafındaki Görüntü

Zaten uygulamamızın IL(Intermediate Language) tarafındaki çıktısına baktığımızda, 0 atamasının yapıldığı yerde InformationType enum sabitinin kullanıldığı versiyonun çağırılacağı da önceden belirtilmiştir.

.method private hidebysig static void  Main(string[] args) cil managed 
{ 
  .entrypoint 
  // Code size       191 (0xbf) 
  .maxstack  3 
  .locals init ([0] class EnumAndZeroConstant.Information infoZero, 
           [1] class [mscorlib]System.Collections.Generic.List`1<class EnumAndZeroConstant.Information> infos, 
           [2] class EnumAndZeroConstant.Information info, 
           [3] class [mscorlib]System.Collections.Generic.List`1<class EnumAndZeroConstant.Information> '<>g__initLocal0', 
           [4] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class EnumAndZeroConstant.Information> CS$5$0000, 
           [5] bool CS$4$0001) 
  IL_0000:  nop 
  IL_0001:  ldc.i4.0 
  IL_0002:  newobj     instance void EnumAndZeroConstant.Information::.ctor(valuetype EnumAndZeroConstant.InformationType)

Sorunun Çözümü

Bu gözden kolayca kaçabilecek bir noktadır. Hani test süreçlerinde Zero-Data diye bir senaryo vardır gerçi ama bu vaka zaten onunla bir değildir. Sadece bir isim benzerliği olduğunu ifade edebiliriz. Bizim burada sorunu nasıl çözebileceğimize bir bakmamız gerekiyor. Mademki ortadabilinçsiz bir tür dönüşümü var(Implicitly Type Conversion) bu durumda dönüşümü bilinçli hale getirmeyi deneyebiliriz(Explicitly Type Conversion). Aşağıdaki kod parçasındaki denemeleri yaptığımızı düşünelim.

Information infoZero1 = new Information((int)0); 
var zeroVar = 0; 
Information infoZero2=new Information(zeroVar); 
object zeroObj = 0; 
Information infoZero3 = new Information(zeroObj); 
int zeroInt = Convert.ToInt32("0"); 
Information infoZero4 = new Information(zeroInt); 
double zeroDbl = 0.0; 
Information infoZero5 = new Information(zeroDbl); 
Information infoZero6 = new Information(0.0); 
var infoZero7 = new Information(0);

List<Information> infos = new List<Information>() 
                              { 
                                                  infoZero1, 
                                                  infoZero2, 
                                                  infoZero3, 
                                                  infoZero4, 
                                                  infoZero5, 
                                                  infoZero6, 
                                                  infoZero7 
                              };

Burada farklı şekillerde 0 değerinin gönderilmesi söz konusu olmuştur. İlk olarak cast operatörü göz önüne alınarak 0 değerinin int tipinden ele alınması denenmiştir. İkinci olarak 0 değişkenini taşıyan bir var tanımlaması yapılmaktadır. Devam eden kısımda sırasıyla Object tipine atanarak yapıcı metoda gönderilme, Convert tipinin static Int32 metodundan yararlanma, double bir değişken atama, yapıcı metoda parametre olarak 0 gönderirken var kullanarak ilerleme seçenekleri de denenmiştir. Bu durumda uygulamanın ekran çıktısı aşağıdaki gibi olacaktır.

Dikkat edileceği üzere yapıcı metoda 0 değeri atama işlemini, dışarıda tanımlanan bir değişken üzerinden gerçekleştirdiğimizde object tipini kullanan yapıcı metoda gidilmiştir. Tabi bu durumdaInformation tipini kullanan geliştiricinin bu durumu göz önüne alması ve öncesinde gerekli dönüşüm işlemlerini yapması gibi bir sorumluluk ortaya çıkmaktadır. Oysaki geliştirici veya Object User çok kolayca durumu gözden kaçırabilir. Daha kalıcı bir çözüm ile ilerlemek gerekmektedir. Bunun için Information tipinin yapıcı metodlarının sayısını arttırıp tipe göre bir aksiyon alınması sağlanabilir. Aşağıdaki kod parçasın görüldüğü gibi.

class Information 
{ 
    public string SummaryMessage { get; private set; }

    public Information(int info) 
    { 
        SummaryMessage = info.ToString(); 
    } 
    public Information(double info) 
    { 
        SummaryMessage = info.ToString(); 
    } 
    public Information(object commonInformation) 
    { 
        SummaryMessage = commonInformation.ToString(); 
    }

    public Information(InformationType informationType) 
    { 
        switch (informationType) 
        { 
            case InformationType.Application: 
                SummaryMessage = "Uygulama bilgisi"; 
                break; 
            case InformationType.System: 
                SummaryMessage = "Sistem bilgisi"; 
                break; 
            case InformationType.Member: 
                SummaryMessage = "Üyeden"; 
                break; 
            default: 
                SummaryMessage = "Bilinmeyen kaynak"; 
                break; 
        } 
    } 
}

Dikkat edileceği üzere int ve double tiplerini parametre olarak alan iki ek yapıcı metod daha ilave edilmiştir. Bu durumda 0 ve 0.0 değerleri için uygun olan yapıcı metodlar devreye girecek, bir başka deyişle InformationType enum sabitin kullanan yapıcı metod göz ardı edilecektir. Tabi yine de çok şık bir çözüm olmadığını ifade etmemiz gerekiyor. Nitekim 0 değerini taşıyabilecek pek çok sayısal tip mevcuttur. Byte, short, float vb…Dolayısıyla bunların her biri için bir aşırı yüklenmiş yapıcı metod yazmak çok da yerinde olmayabilir. Yine de Information tipini kullanacak olan geliştirici için hata riski bu şekilde azaltılabilir. Uygulamayı bu haliyle çalıştırdığımızda aşağıdaki ekran çıktısını elde ederiz.

İstediğimiz sonuca ulaştık. Görüldüğü üzere Enum sabitlerini yapıcı metodlara parametre olarak geçirdiğimizde, göndereceğimiz 0 sabit değeri otomatik olarak bir enum sabiti tipine dönüştürülmektedir. Dolayısıyla söz konusu sınıf içerisinde object tipini kullanan başka bir yapıcı metod varsa, tedbir almadığımız durumda fark etmeyeceğimiz bir çalışma zamanı sonucu üretilebilir. Böylece geldik bir makalemizin daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.

Yazar Hakkında

Burak Selim Şenyurt

Burak Selim Şenyurt

buraksenyurt.com

Yıldız Teknik Üniversitesi Matematik Mühendisliği mezunu olan Şenyurt, 1999 yılında profesyonel olarak adım attığı yazılım dünyasında, 2003 yılından beri Microsoft .Net teknolojileri ile ilgilenmektedir. Yazılım hayatına Assist Line isimli Call Center firmasında Delphi programcısı olarak başlayan Şenyurt sonrasında, sırasıyla Bizitek(Junior Developer), Netron(Master Trainer), Citibank(Outsource Senior Software Developer), Innova(Application Development Consultant), ve TCM(Software Architect) firmalarında görev almıştır. Su anda ING Bank bünyesinde Kıdemli Yazılım Danışmanı olarak görev yapmaktadir. 2006, 2007 yıllarında C#, 2008,2009,2010 yıllarında ise Connected System Developer kategorisinde Microsoft MVP seçilen Şenyurt, evli ve 1 çocuk babasıdır. C# diline olan düşkünlüğü, oğluna S(h)arp adının verilmesinde önemli bir etken olmustur.

Sosyal Medya

ORANLAR

  • 4606izleme

Arkadaşlarınla Paylaş

  • Tweet

0 Yorum

Yorum Yaz / Soru Sor

Lütfen yorum yazmak veya soru sormak için üye girişi yapınız.

Son Yorumlar

  • Böyle bir sayfalama ağ trafiğini hafifleti...
  • Böyle bir sayfalama ağ trafiğini hafifleti...
  • Merhaba, ellerinize sağlık çok yardımcı ol...
  • Merhaba Bu uygulama örneğinden ASP.net ...
  • Hocam Link başka sayfaya yönlendiriyor.

En Güncel Sorular

  • Bilgilendirme maili (C#.Net)
  • Power Pivot (Sharepoint 2010)
  • BigInteger, BigDecimal (Asp.Net ve Asp.Net MVC)
  • visual C# ile asp nette veritabanı islemleri (Asp.Net ve Asp.Net MVC)
  • Share Point ile Dosya Arşiv Yönetim Sistemi yapılabilir mi ? (Sharepoint 2010)

En Son Cevap Verilen Sorular

  • Bilgilendirme maili
  • BigInteger, BigDecimal
  • visual C# ile asp nette veritabanı islemleri
  • Share Point ile Dosya Arşiv Yönetim Sistemi yapılabilir mi ?
  • txt dosyasına veri yazma

Twitter

Takip et: @yazilim_dilleri

En Çok Okunanlar

Elif BAYRAKDAR

C# ile SQL Server Bağlantısı, Insert, Update ve Delete Sorguları

23.05.2013

  • 124113
  • 0
Hakan Keskin

C# ile Windows Service Projesi Oluşturma, Debug Etme ve Setup Hazırlama

17.12.2013

  • 71306
  • 0
batuhan avlayan

Php - Mail Gönderme (İletişim Formu)

02.09.2013

  • 51908
  • 0

Sponsorlar

KODLAB
Pluralsight
Exchange server is
Office 365
YAZILIM DİLLERİ
Yukarı Çık
  • Hakkımızda
  • Facebook
  • Twitter
  • RSS

© Yazılım Dillerinin Buluşma Noktası | Kaynak belirtildiği sürece makaleler kopyalanabilir.
YazilimDilleri.Net sitesinde yer alan kullanıcıların oluşturduğu tüm içeriklerin yayınlanması ile ilgili yasal yükümlülükler içeriği oluşturan kullanıcıya aittir, YazilimDilleri.Net hiçbir şekilde sorumlu değildir.

Kapat

Giriş Yap

Kullanıcı Adı

Şifre

Şifremi Unuttum

KULLANICI GİRİŞİ