Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Cenk Özdemir
Cenk Özdemir
http://www.csharpnedir.com/
İletişme geçmek için tıklayın.
4 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: #error #pragma #undef birlikte derleme direktifi direktifleri ilgili kaynak kosulu kullanarak kullanim main(string[] sirasinda static C# / VC#/.NET Cenk Özdemir
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : Orta
Kategori : C# / VC#/.NET
Yayınlanma Tarihi : 2.7.2007
Okunma Sayısı : 36838
Yorum Sayısı : 2     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 21.11.2024
Turhal Temizer
Mac OS/X Removing CUDA 21.11.2024
Burak Selim Şenyurt
Rust ile ECS Yaklaşımını Anlamak 21.11.2024
Burak Selim Şenyurt
Birlikte Rust Öğrenelim Serisi 21.11.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
C#'ta Önişlemci Direktifleri
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
    Bu makalemizde, özellikle C programcılarının yakından tanıdıkları önişlemci direktiflerinin C# tarafında nasıl yer aldıklarını incelemeye çalışacağız. C ile daha önceden uğraşmış bir uygulama geliştiricisi için "önişlemci" ve "önişlemci direktifi" kavramları çok da yabancı değildir; ancak bir .NET programcısı açısından bakarsanız önişlemci direktifleri çok da fazla kullanılmayan, hakkında fazla konuşulmayan bir konudur. Bu yüzden işin C# tarafına geçmeden önce çok kısa bir şekilde "önişlemci" ve "önişlemci direktifi" kavramlarına C penceresinden bakmakta fayda vardır.
    Aşağıda, bir C programının çalışma sürecini gösteren şemayı incelediğimizde .NET mimarisinden farklı olarak derleyiciden önce çalışan başka bir yapı görürüz: Önişlemci. Bu yapının görevi, en kaba tabirle, kaynak kodu derleyiciye ulaşmadan önce düzenlemektir. Biraz daha açmak gerekirse C önişlemcisinin; yorum satırlarının atılması, makro tanımlanması, boş karakterlerin silinmesi gibi işleri yaptığı sayılabilir.



    C önişlemcisinden kısaca bahsettiğimize göre gelelim önişlemci direktiflerine. Önişlemci direktifleri ise kaynak kod içerisine yazdığımız ve önişlemci tarafından ele alınarak bazı işler yapmamıza imkan veren özel direktiflerdir. Önişlemci, bu direktifler doğrultusunda bir çıktı oluşturarak derleyiciye ( compiler ) verir. Böylece derleme işlemine yön verilebilir, ekstra bir takım işler yaptırılabilir.
    Sanırım önişlemci direktifleriyle ilgili birçok soru işaretini yok etmiş olduk; tabi bununla birlikte birçok soru işareti de oluşturduk. C’deki süreç tamam, ama C# tarafında işler nasıl yürüyor olabilir? .NET mimarisi içinde de önişlemci diye bir yapı bulunur mu? C#’ta kullanabileceğimiz önişlemci direktifleri nelerdir ve hangi amaçla kullanılırlar? Yazının geri kalanında bu ve bunun gibi sorulara cevap vermeye çalışacağız.
    Öncelikle C#’ta kullanabileceğimiz önişlemci direktiflerini kullanım amaçlarına göre listeleyelim. Daha sonra bu direktiflerin her birini kısa kısa örneklerle mercek altına alalım.

Koşullu derleme
#define
#undef
#if
#else
#endif
#elif
Derleme
#error
#warning
#line
#pragma
Görsel
#region
#endregion
 
 C#’ta önişlemci direktifleri her ne kadar "önişlemci direktifleri" olarak adlandırılsalar da aslında bu isimlendirme yüzde yüz doğru değildir. Çünkü, .Net mimarisinde önişlemci diye bir kavram bulunmamaktadır. Ancak, alışılagelen önişlemci direktifleri gibi kullanıldıkları ve aynı davranışları gösterdikleri için bu şekilde bir adlandırmaya da yanlış denilemez.
A)Koşullu Derleme

a)Nedir?


   Temel çalışma mantığı if-else karar yapısından farklı olmamakla birlikte, #if-#endif anahtar kelimeleriyle tanımlanmış bir kod bloğu, yalnızca koşul sağlandığı taktirde derlenir. Örnek olarak aşağıdaki kodu inceleyelim.

static void Main(string[] args)
{
   Console.WriteLine("TEST");

   #if true
      Console.WriteLine("Kosul saglandi");
   #else
      Console.WriteLine("Kosul saglanmadi");
   #endif
}

Programın CIL çıktısına baktığımızda, koşulun sağlanmadığı durumlarda çalışacak olan kodun derlenmediğini görürürüz.
 
.method private hidebysig static void Main(string[] args) cil managed
{
   .entrypoint
   // Code size 24 (0x18)
   .maxstack 8
   IL_0000: nop
   IL_0001: ldstr "TEST"
   IL_0006: call void [mscorlib]System.Console::WriteLine(string)
   IL_000b: nop
   IL_000c: ldstr "Kosul saglandi"
   IL_0011: call void [mscorlib]System.Console::WriteLine(string)
   IL_0016: nop
   IL_0017: ret
} // end of method Program::Main
Ancak burada #if direktifinin kullanımındaki kısıtların altını çizmek gerekmektedir. Tipik if karar yapısında, parantez içerisinde bool tipinden bir değişken kullanabilirken, #if önişlemci direktifinde böyle bir imkanımız yoktur. Benzer şekilde, #if direktifinde koşul olarak a<b, 1==1 gibi ilişkisel operatörlerin kullanımları da mümkün değildir. Peki öyleyse bu direktifi yalnızca true ya da false anahtar kelimeleriyle mi kullanabiliriz? Tabi ki hayır. Zaten takdir edersiniz ki bu kullanım çok da işe yarar görünmüyor. Bunun yerine, yine bir önişlemci direktifi olan #define ifadesinden faydalanarak kendi koşullarımızı tanımlayabilir ve bu koşulları #if ile birlikte kullanabiliriz.

 if(true)
    Console.Write("a");
 else
    Console.Write("b");

 Normal if kullanımında da gerçeklememesi kesin olan satırlar ( Unreachable code ) programın IL çıktısında yer almaz.
b) #define önişlemci direktifi nasıl kullanılır?

  
#if ifadesinde kullanmak üzere koşul tanımlamak için #define direktifinden faydalanırız. Örnek kullanım için aşağıdaki kodları inceleyelim.

#define KONTROL
using System;

namespace OnIslemciDirektifleri
{
   class Program
   {
      static void Main(string[] args)
      {
                 
         #if KONTROL
            Console.Write("Kosul ");
            Console.WriteLine("saglandi");
         #else
            Console.WriteLine("Kosul saglanmadi");
         #endif
      }
   }
}
Yukarıdaki kaynak kodu çalıştırdığımızda, KONTROL koşulunun daha önce tanımlanmış olmasından ötürü #if-#else içerisinde kod bloğu işletilecektir.
Dikkat etmek gereken nokta, koşulun tanımlandığı yerin tüm kodun üzerinde ( using bloğunun da) oluşudur. Aksi taktirde kaynak kod derlenmez.



c)Farklı "koşul tanımlama" yolları

   1-Proje özelliklerinde koşul tanımlama
   
   
#define önişlemci direktifi dışında, proje özelliklerinden faydalanarak da koşul tanımlaması yapılabilir. Bunun için proje özellikleri altındaki Build seçeneğinde, "Conditional compilation symbols" yazan yere derleme koşullarını söylemek gerekir. Birden fazla koşul tanımlaması yapılırken, koşullar arasında bir boşluk bırakılabilir,virgül ya da noktalı virgül konabilir. Örnek olarak aşağıdaki gibi bir koşul tanımlamasının sonuçlarını inceleyelim.
 
  

using System;

namespace OnIslemciDirektifleri
{
   class Program
   {
      static void Main(string[] args)
      {
                 
         #if CENK
            Console.WriteLine("CENK kosulu tanimli");
         #endif          #if OZDEMIR
            Console.WriteLine("OZDEMIR kosulu tanimli");
         #endif


         // Tanımlanan kosullar iki kelimeden olusamazlar.Dolayısıyla asagidaki kod hata üretir.
         //#if CENK OZDEMIR
         //   Console.WriteLine("CENK OZDEMIR kosulu tanimli");
         //#endif
      }
   }
}


    2-Komut satırında koşul tanımlama

   
Komut satırından csc.exe’yi kullanarak yaptığımız derleme sırasında da koşul tanımlama imkanımız vardır. Bunun için, derlenmesini istediğimiz kaynak kod dosyasının adını söyledikten sonra /define anahtarından faydalanmak gereklir.

Test.cs
using System;

namespace OnIslemciDirektifleri
{
   class Program
   {
      static void Main(string[] args)
      {                 
         #if KOSUL1
            Console.WriteLine("KOSUL1 tanimli");
         #endif

         #if KOSUL2
            Console.WriteLine("KOSUL2 tanimli");
         #endif
      }
   }
}
Daha sonra kaynak kodumuzu komut satırından aşağıdaki gibi derleyip çalıştıralım.



d)Tanımlanmış bir koşulu kaldırmak = #undef önişlemci direktifi

  
Tanımlanmış bir koşulu kaldırmak için #undef direktifinden faydalanılır. Örnek olarak aşağıdaki kodu inceleyelim.

#define DENEME
#undef DENEME

using System;

namespace OnIslemciDirektifleri
{
   class Program
   {
      static void Main(string[] args)
      {                 
         #if DENEME
            Console.WriteLine("DENEME tanimli...");
         #else
            Console.WriteLine("DENEME tanimli degil...");
         #endif
      }
   }
}


Ancak, kabul edersiniz ki kaynak kod içerisinde bir koşul tanımlayıp kaldırmak demek, o koşulun hiç tanımlanmamış olmasıyla eşdeğerdir. Dolayısıyla #undef direktifini işe yarar şekilde kullanabilmek için koşul tanımlamasını kaynak kod dışında yapmak gerekir. Bu da proje özelliklerini ya da komut satırını kullanarak yaptığımız koşul tanımlamalarını kaynak kod içerisinde ezebileceğimiz anlamına gelir. Yani kaynak kod dışında bir koşul tanımlaması yapılırsa, tanımlanmış koşul kaynak kod içerisinden #undef direktifi ile kaldırılabilir.

Test.cs
#undef IKINCI

using System;

namespace OnIslemciDirektifleri
{
   class Program
   {
      static void Main(string[] args)
      {
         #if BIRINCI&&IKINCI
            Console.WriteLine("BIRINCI ve IKINCI kosul tanimli");
         #elif BIRINCI
            Console.WriteLine("BIRINCI kosul tanimli,IKINCI kosul tanimli degil");
         #elif IKINCI
            Console.WriteLine("IKINCI kosul taimli,BIRINCI kosul tanimli degil");
         #endif
      }
   }
}


e)Conditional Niteliği ( Attribute )

  
Conditional niteliği metot ya da nitelik sınıflarına ( attribute classes ) uygulanarak, ilgili metot ya da niteliğin kullanılmaya çalışılığındaki davranışını belirler. Bahsettiğimiz bu noktalarda #if-#endif kullanımı mümkün olmadığından böyle bir niteliğe ihtiyaç duyulmuştur. Benzer şekilde #if-#endif kullanabildiğimiz noktalarda da Conditional niteliğini kullanamayız.

 Conditional niteliği, yalnızca geriye değer döndürmeyen metotlar ve nitelik sınıflarıyla ( attribute classes ) birlikte kullanılabilir.
Aşağıdaki örneği inceleyelim.

using System;
using System.Diagnostics;

namespace OnIslemciDirektifleri
{
   class Program
   {
      static void Main(string[] args)
      {
         UcgenCiz();
      }

      [Conditional("TEST")]
      static void UcgenCiz()
      {
         Console.WriteLine("*\n**\n***\n****\n*****");
      }
   }
}
Programın çıktısı aşağıdaki gibidir.



UcgenCiz() metodunun çalışmadığını görüyoruz. Peki metodun kendisi IL kodunda yer almış mıdır? Test  için IL Dissambler ( ildasm ) aracını kullanarak programın IL çıktısına bakalım.




IL çıktısından da görüldüğü üzere Conditional niteliği uygulanmış metot derlenir; ancak çağırılmaz.

B)#error, #warning, #line, #pragma

a)Derleyiciye hata ve uyarı verdirmek

  
Derleyicinin, derleme işlemini engelleyecek şekilde bir hata üretmesini sağlamak için #error, derleme işlemini engellemeden bir uyarı üretmesini sağlamak için de #warning direktifi kullanılır.

using System;

namespace OnIslemciDirektifleri
{
   class Program
   {
      static void Main(string[] args)
      {
         int sayi = 1 / 0;
      }

      static void Baglan()
      {
         #error Baglan metodu henüz yazılmadı.
      }

      static bool KullaniciBul(int id)
      {
         #error KullaniciBul metodu henüz yazılmadı.
      }

      static bool KullaniciSil(int id)
      {
         #warning KullaniciSil metodu henüz yazılmadı.
      }
   }
}
Yukarıdaki kodu derlemeye çalıştığımızda Error List aşağıdaki gibi görünür.



Burada dikkatinizi çekmek istediğim nokta, #error direktifini kullandığımızda, kodtaki diğer hataları ele alamıyor oluşumuzdur. Aslında kodumuz içerisinde üç tane hata mevcut ( 0’a bölmeye çalıştığımız satır, geriye bir şey döndürmeyen KullaniciBul(int id) ve KullaniciSil(int id) metotları ) olmasına rağmen, yalnızca  #error ve #warning direktiflerince üretilen hata ve uyarılar ele alınabilmektedirler.

b)#line önişlemci direktifi

    1-Satır numaralarıyla oynamak

    
#line direktifini kullanarak kaynak kodumuzun nasıl satırlandırılacağını söyleyebiliriz. Bu kullanıma örnek olarak da aşağıdaki kodu inceleyelim.

using System;

namespace OnIslemciDirektifleri
{
   class Program
   {
      static void Main(string[] args)
      {
         #line 55 "bizimDosya"
            int sayi1 = 1 / 0; //10
         #line 10 "bizimDosya" //11
            int sayi1; //12
         #line 80 "bizimDosya" //13
                                      //14
            int sayi2 = 1 / 0; //15
         #line 1 "sizinDosya"  //16
            int sayi2; //17
      }
   }
}
Kod derlendikten sonra, hata oluşan satırlar 10,12,15 ve 17 olmasına rağmen aşağıdaki Error List görünür.



    2-Hata ayıklayıcısına yön vermek

   
#line önişlemci direktifinin bir diğer kullanım alanı da hata ayıklama sırasında içerisine girmek istemediğimiz kod blokları oluşturmaktır.

using System;

namespace OnIslemciDirektifleri
{
   class Program
   {
      static void Main(string[] args)
      {
         #line hidden
         Console.WriteLine("Cenk");
         Console.WriteLine("Özdemir");

         #line default
         Console.Write("C#");

         #line hidden
         Console.WriteLine(" Nedir?");
      }
   }
}
Örnekteki kod içerisindeki hatalar ayıklanırken ( debug ) adım adım ilerlediğimizde, "#line hidden" satırından sonraki satırlara geçilmez, "#line default" satırına gelindikten sonra ise normal davranışa geri dönülür.

c) #pragma önişlemci direktifi


   1- Uyarıları düzenlemek = #pragma warning

   C#’ta zaman zaman kodun çalışmasına engel teşkil etmeyen uyarılarla karşılaşırız. #pragma warning ifadesi ise bize tüm uyarıları ya da belli bir uyarıyı kapatıp/açma, kısaca uyarıları yönetme olanağı sunar. Örnek kullanım için aşağıdaki kodu inceleyelim.

  


 Tüm uyarılarlarla ilgili seçenekleri, proje özelliklerinde ( Project Properties ) kod analiz ( Code Analysis ) seçeneği altında bulabilirsiniz.
   2- #pragma checksum

  
Aynı isme sahip kaynak kod dosyalarının hata ayıklanması ( debug ) sırasında karışıklık yaratmaması için, ilgili pdb dosyasında bir kontrol verisi ( checksum ) bulunur. Bu özellik Visual Studio 2005 ile birlikte gelmiştir ve bahsettiğimiz isim karmaşasının önüne geçerek, hata ayıklayıcısının ( debugger ) doğru dosyayı kullandığının doğrulamasını sağlar. Ancak bu yöntem ASP.NET projelerinde çalışmaz. Çünkü, kontrol verisi .aspx sayfaları için değil kaynak kod için oluşturulur. Dolayısıyla farklı yollar altındaki aynı isimli .aspx dosyaları, hata ayıklanması sırasında problem yaratabilir. Böyle bir durumda #pragma checksum ifadesi ile ASP.NET projelerinde .aspx sayfaları için cheksum oluşturulabilir.

#pragma checksum "Default.aspx" "{3673e4ca-6098-4ec1-890f-8fceb2a794a2}" "012345678AB14232"
C)Görsel önişlemci direktifleri: #region-#endregion

  
#region ifadesi, Visual Studio ile çalışırken kaynak kodları saklamak için kullanılır. Sadece, uygulama geliştiricisine görsel anlamda kolaylık sağlar, bunun dışında programa herhangi bir etkisi yoktur.

   Örnek

  
    
     

Böylece, C# önişlemci direktiflerini incelemeye çalıştığımız makalemizin de sonuna geldik. Bir dahaki makalede görüşmek üzere, hoşçakalın.

Cenk Özdemir

Makale:
C#'ta Önişlemci Direktifleri C#, Visual C# ve .NET Cenk Özdemir
  • Yazılan Yorumlar
  • Yorum Yaz
ARA
3
2009
benim yaardıma ihtiyacım var form açılır açılmaz kaybolup görünen listbox da yazılan kodlara ihtiyacım var 2 farklı isim yazıcam form acılır acılmaz çalışmaya başlicak cvb bekliyorummmm
TEM
3
2007
bu konuya daha once hiç dikkat etmemiştim. nasılsa önişlemci ile ilgili bir işimiz yok diye. yazınızı okudum gerçekten güzel sade bir şekide yazılmış. kodları daha denemedim fakat aklımda bunları kullanabileceğim yerler ile ilgili birşeyler oluşmaya başladı. çok teşekkürler...
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor