C# ile XML Serileştirme (serialization)

28 Ara

XML yapısı metin tabanlı bir standarttır. HTML yapısına çok benzer biçimde oluşturulmuştur ve notepad ile bile okunabilir bir dokümandır. XML sayesinde artık dökümanlar(Microsoft Office dökümanları), resim, müzik, binary dosyalar ve veritabanı bilgileri saklanabilmektedir.

.Net Framework’te xml dostalarının okunması ve yazılması işlemlerini barındıran kütüphaneler System.Xml.Serialization ad uzayındadır.

XML Serileştirmenin Avantajları

XML yapısının en büyük avantajlarından biri platform bağımsızlığıdır. Yani herhangi bir işletim sisteminde veya herhangi bir uygulamada oluşturulmuş bir XML döküman .Net tarafından rahatça kullanılabilir. Diğer avantajları şu şekilde sıralayabiliriz.

  • XML metin tabanlı bir satandart olduğundan tüm platformlar XML işlemlerini gerçekleştirebilen kütüphaneler bulunur. Bu sayede platform uyumluluğu vardır.
  • XML yapıda serileştirilen nesneler, Notepad gibi metin editörleri tarafından görüntülenebilmektedir.

XML yapıdaki serileştirmelerde  birçok kolaylık sağlanmış olsada aşağıdaki gibi bazı sınırlamalar da vardır.

  • XML serileştirmede sadece public veriler serileştirilir. Private veriler serilştirilmez.
  • Grafiksel objeler serileştirilemez, sadece nesneler serileştirilir.

Örnek:


    FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate);
    XmlSerializer serializer = new XmlSerializer(typeof(DateTime));
    serializer.Serialize(stream, System.DateTime.Now);

Örnek:


    FileStream stream = new FileStream(fileName, FileMode.Open);
    XmlSerializer serializer = new XmlSerializer(typeof(DateTime));
    DateTime date = (DateTime)serializer.Deserialize(stream);

XML ile serileştirilebilen sınıflar oluşturmak

XML ile serileştirilecek bir sınıf oluşturulurken şu kurallara dikkat etmek gerekmektedir.

  • Sınıf erişimi public olarak belirlenmelidir.
  • Serileştirilmek istenen tüm sınıf üyeleri public olmalıdır.
  • Parametresiz kurucu metodlar(constructors) oluşturulmalıdır.

Standart serileştirmedeki gibi sınıfın [Serializable] ile imzalanmasına gerek yoktur.


[XmlRoot("CartItems")]
public class CartItems
{
   [XmlAttribute]
   public int Id { get; set; }
   public string Name { get; set; }
   public decimal Price { get; set; }
   public int Quantity { get; set; }
   [XmlIgnore]
   public decimal Total { get { return Price * Quantity; } }
}

Yukardaki sınıfa ait bir nesnenin XML olarak serileştirildiğinde oluşacak XML içeriği aşağıdaki gibidir.


<?xml version="1.0"?>
 <CartItems Id="2" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Name>Book</Name>
    <Price>5.96</Price>
    <Quantity>2</Quantity>
 </CartItems>

Dataset nesnelerini XML olarak serileştirme

Public erişimli bir sınıfa ait nesnelerinin serileştirildiği gibi DataSet nesnelerini de serilştirmek mümkündür.

    DataSet dataSet = new DataSet("MyDataset");
    DataTable dataTable = new DataTable("Users");
    DataColumn dataColumn = new DataColumn("FirstName");
    DataColumn dataColumn2 = new DataColumn("LastName");

    dataSet.Tables.Add(dataTable);
    dataTable.Columns.Add(dataColumn);
    dataTable.Columns.Add(dataColumn2);

    for (int i = 0; i < 10; i++)
    {
       DataRow row = dataTable.NewRow();
       row[dataColumn] = "User" + i;
       row[dataColumn2] = "Last Name" + i * 2;
       dataTable.Rows.Add(row);
    }

    FileStream stream = new FileStream("Dataset.xml", FileMode.OpenOrCreate);
    XmlSerializer seri = new XmlSerializer(typeof(DataSet));

    seri.Serialize(stream, dataSet);
    stream.Close();

Örnekte görüldüğü gibi sadece dataset nesnesi oluşturularak XmlSerializer yardımıyla serileştirme işlemi kolayca yapılabilmektedir.

Umarım faydalı bir yazı olmuştur. Herkese iyi çalışmalar.

C# ile serileştirme (serialization)

24 Ara

Veri merkezli uygulamalarda verileri saklamak veya transfer etmek gibi durumlarla sık sık karşılaşırız. Verilerin bir kaynaktan alınması veya bir yere depolanması nesneler aracılığı ile gerçekleştirilir. Ancak her programlama dilinde farklı yani platformda kendine özgü bir nesne yapısı olduğundan dolayı, bir platformun diğerinin nesne yapısını bilmesi beklenemez. Bu gibi durumlarda verilerin platform bağımsız bir şeklide depolanması veya transfer edilmesi amacıyla bazı standartlar oluşturulmuştur. Bu standartlardan bazıları Binary, Simple Object Access Protocol(SOAP), JSON veya XML şeklinde belirlenmiştir.

Serileştirme nedir?

Bir nesnedeki verinin bir yerde depolaması veya ağ ortamında bir yerden bir yere gönderilmesi gerektiği durumlarda uygun formata dönüştürülmesi işlemine serileştirme denir. Serileştirilen nesneler veritabanı, hafıza veya dosya gibi ortamlarda saklanabilirler.

serialization

 

 

 

 

 

Deserialization ise bu işlemin tam tersidir.

.Net Framework ile serileştirme

Serileştirme işlemini ve serileştirilmiş nesneleri dönüştürme işlemini gerçekleştirecek olan nesneler, System.Net.Runtime.Serialization ad uzayında bulunmaktadır. Serialization işlemi, bir nesneyi, depolamak veya serileştirmek amacıyla istenen formata dönüştürme işlemidir. Deserialization ise serileştirilmiş biçimdeki verilerin tekrar nesnelere dönüştürülmesi işlemidir. Örneğin, network ortamında bir bilgisayardan başka bir bilgisayara veri transferi gerçekleştirmek için önce bağlantı kurulur, ardından gönderilecek olan nesne oluşturduğumuz uygulama tarafından serileştirilir, daha sonra uzak bilgisayardaki uygulama tarafından deserialization işlemi ile aktarılan veri anlamlı bir nesneye dönüştürülür.

  1. Binary Serialization
  2. SOAP Serialization
  3. JSON Serialization

1-Binary Serialization / Deserialization (İkili Serileştirme)

Binary serişeltirme işlemi için gerekli olan sınıflar  System.Runtime.Serialization.Formatters.Binary altında bulunurlar.

  • Binary serialization işleminde nesneler byte array şekline dönüştürülür.
  • Binary deserialization işleminde byte array şeklindeki tekrar nesneye dönüştürülür.
 public static byte[] BinarySerialize(object graph)
 {
     using (var stream = new MemoryStream())
     {
         var formatter = new BinaryFormatter();
 
         formatter.Serialize(stream, graph);

         return stream.ToArray();
     }
 }

 public static object BinaryDeserialize(byte[] buffer)
 {
     using (var stream = new MemoryStream(buffer))
     {
        var formatter = new BinaryFormatter();

        return formatter.Deserialize(stream);
     }
 }

Burada binary serialization işlemini gerçekleştiren BinaryFormatter sınıfıdır. BinaryFormatter sınıfı parametre olarak bir Stream nesnesi aldığı için MemoryStream kullanılmıştır.

Örnek: Serileştirme işlemi sırasında kullanılacak olan veri tipimiz PlaceOrder isminde bir sınıf olsun.


 [Serializable]
 public class PlaceOrder
 {
     public Guid Id { get; set; }
 }

Bu sınıfa ait bir verinin serileştirme işlemi şu şekilde gerçekleştirilir.


 public class Program
 {
     static void main(string[] args)
     {
         PlaceOrder order = new PlaceOrder();
         var seralized = BinarySerialize(order);
         var deserialized = BinaryDeserialize(serialized);
     }
 }

Not: Yukarıdaki örnekte PlaceOrder sınıfı [Serializable] attribute ile işaretlenmiş ve serileştirilebilir hale getirilmiştir. Bu işaretleme BinaryFormatter kullanarak yapılan serileştirme işlemlerinde zorunludur. Aksi taktirde runtime esnasında SerializationException hatası oluşacaktır.

serializationexception

Serileştirilebilir sınıflar nasıl oluşturulur?

Bir sınıfa ait nesneleri serileştirilebilir hale getirmek için sınıfa ait nesnelerin [Serializable] ile imzalanması gerekmektedir. Serileştirme işlemini gerçekleştirdiğinizde runtime esnasında private erişimli üyeler dahil tüm sınıf üyeleri serileştirilir.

Örnek:

    [Serializable]
    public class PlaceOrder
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

Sınıf içersinde bir üyeyi serileştirmeden hariç tutmak için o üyenin [NonSerialized] ile imzalanması gerekmektedir.

Örnek:

    [Serializable]
    public class PlaceOrder
    {
        public Guid Id { get; set; }
        [NonSerialized]
        public string Name { get; set; }
    }

Bu şekilde Name üyesi serileştirme işlemine dahil edilmeyecektir.
Serileştirilmemiş nesneler ile deserialization işlemi sonrası işlem yapmak için IDeserializationCallback.OnDeserialization metodunu çağırarak, bu metod içerisinde istenen işlemleri gerçekleştirebiliriz.

Örnek:

    [Serializable]
    public class ShoppingCartItem: IDeserializationCallback
    {
       public string Name { get; set; }
       public int Quantity { get; set; }
       public decimal ListPrice { get; set; }
       [NonSerialized]
       public decimal Total;

       #region IDeserializationCallback Members
        public void OnDeserialization(object sender)
        {
           Total=Quantity*ListPrice;
        }
       #endregion
    }

2-SOAP Serialization / Deserialization (SOAP Serileştirme)

Bir nesnenin Simple Object Access Protocol(SOAP) protokolü üzerinden transfer edilebilmesi için bu protokole uygun bir şekilde serileştirilmesi ve serileştirilen nesnenin tekrar nesneye dönüştürülmesi işlemleridir. SOAP serileştirme işlemleri için gerekli sınıflar System.Runtime.Serialization.Formatters.Soap altında bulunurlar.

 
   public static string SoapSerialize(object graph)
  {
     using (var stream = new MemoryStream())
     {
        var formatter = new SoapFormatter();

        formatter.Serialize(stream, graph);
 
        return Encoding.UTF8.GetString(
                  stream.GetBuffer(), 0, (int)stream.Position);
     }
  }

  public static object SoapDeserialize(string buffer)
  {
     using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(buffer)))
     {
         var formatter = new SoapFormatter();

         return formatter.Deserialize(stream);
     }
  }

Örnek: SOAP serileştirilmiş bir nesnenin görünümü:


 public class Program
 {
     static void main(string[] args)
     {
         PlaceOrder order = new PlaceOrder
         {
             Id = Guid.NewGuid()
         };
         var soapseralized = SoapSerialize(order);
         var soapdeserialized = SoapDeserialize(soapserialized);
     }
 }

soap serialization

3- JSON Serialization

Nesneleri JSON şeklinde serileştirme işlemi için Json.Net kütüphanesi kullanılabilir. Bu kütüphane nuget paketi olarak bu adresten indirilebilir.

 
  public static string JsonSerialize(object graph)
  {
      return JsonConvert.SerializeObject(graph);
  }

  public static object JsonDeserialize(string seralized)
  {
      return JsonConvert.DeserializeObject(seralized);
  }

Örnek JSON serileştirilmiş nesne.
json

Not: Json serileştirme sonucunda .Net ile ilgili bilgiler Json nesnesine eklenmez. Örneğin nesnenin hangi namespace ve hangi sınıfa ait olduğu bilgisi yoktur. Bu bilgilerinde eklenmesini istiyorsanız JsonSerializerSettings sınıfını serileştirme ve deserileştirme işlemi sırasında kullanmalısınız. JsonSerializerSettings sınıfının TypeNameHandling üyesi TypeNameHandling.Objects şeklinde düzenlenmelidir.

 
 public static string JsonSerialize(object graph)
 {
     return JsonConvert.SerializeObject(graph, 
         Formatting.None, 
         new JsonSerializerSettings
         {
            TypeNameHandling = TypeNameHandling.Objects
         });
 }

 public static object JsonDeserialize(string seralized)
 {
     return JsonConvert.DeserializeObject(seralized, 
         new JsonSerializerSettings
         {
            TypeNameHandling = TypeNameHandling.Objects
         });
 }

json

[Serializable] Attribute Kullanmadan Binary Serileştirme

BinaryFormatter veya SoapFormatter kullanarak serileştirme işlemleri gerçekleştirilen sınıfların [Serializable] attribute ile imzalanması gerektiğini söylemiştik. Ancak Json serileştirme yaparken sınıfların [Serializable] attribute ile imzalanmasına gerek yoktur.


 public class PlaceOrder
 {
     public Guid Id { get; set; }
 }

PlaceOrder sınıfına ait nesneler JsonConvert ile [Serializable] attribute olmadan serileştirilebilir.

Bu durumda eğer BinaryFormatter veya SoapFormatter gibi serileştirme işlemlerinden önce JsonConvert ile serileştirme yapılıp ardından binary serileştirme yapıldığında sınıfların [Serializable] attribute ile imzalanmasına gerek kalmaz.

Örnek:


 public static byte[] BinarySerializeWitoutSerializable(object graph)
 {
   using (var stream = new MemoryStream())
   {
      var formatter = new BinaryFormatter();

      formatter.Serialize(stream, JsonConvert.SerializeObject(graph));

      return stream.ToArray();
   }
 }

Ancak bu durumda art arda iki defa serileştirme işlemi gerçekleştirilmiş olur.

.Net Framework Dosya Sistemine Genel Bakış

19 Ara

Dosya, klasör ve sürücü işlemleriyle ilgili sınıflar System.IO ad uzayında bulunmaktadır. Dosya sistemi ile ilgili snıflar bilgilendirme ve hizmet amaçlı olarak iki grupta incelenmektedir.

ilgi amaçlı sınıfların çoğu FileSystemInfo sınıfından türetilmiştir. Bu sınıflar dosya sistemi nesneleri (dosya, klasör ve sürücüler) hakkında bütün bilgileri vermektedir. Bilgi sınıfları FileInfo ve DirectoryInfo adında iki sınıftır.

Ayrıca DriveInfo sınıfı da sistemdeki bir sürücüyü temsil etmektedir. Ancak bir bilgilendirme sınıfıdır. FileSystemInfo sınıfından türetilmediği için de sürücü silme gibi bazı davranışları göstermez.

Hizmet amaçlı sınıflar dosya, dizin ve dosya yolları üzerinde bazı işlemleri gerçekleştirmek için bazı statik metodlar sunarlar. Hizmet sınıfları File, Directory ve Path sınıflarıdır.

FileSystemInfo Sınıfı

Bu sınıf dosya sistemindeki bilgilendirme sınıflarına temel oluşturur. FileSystemInfo sınıfının özellikleri ve metodları aşağıdaki gibidir.

Özellikler: Attribures, CreationDate, Exist, Extension, FullName, LastAccessTime, LastWriteTime, Name

Metodlar: Delete, Refresh

FileInfo Sınıfı

Dosya sistemindeki tek bir dosyaya erişmek için gerekli işlevselliği sağlar.

Özellikler: Dictionary, DirectoryName, IsReadOnly, Length

Metodlar: AppendText, CopyTo, Create, CreateText, Decrypt, Encrypt, MoveTo, Open, OpenRead, OpenText, OpenWrite, Replace

Örnek 1: Dosya bilgisine erişmek.

FileInfo file = new FileInfo(@"c:\test.txt");

if (file.Exists)
{
   Console.WriteLine("File Name: {0}      ", file.Name);
   Console.WriteLine("File Path: {0}      ", file.FullName);
   Console.WriteLine("File Size: {0} bytes", file.Length);
}

Örnek 2: C sürücüsündeki bir dosyayı uygulamanın çalıştığı debug dizinine kopyalamak.

FileInfo file = new FileInfo(@"c:\test.txt");
file.CopyTo("copyOfText.txt");

 

Örnek 3: Klasördeki dosyalara erişmek

DirectoryInfo info = new DirectoryInfo(@"c:\windows");

foreach (FileInfo item in info.GetFiles())
{
   Console.WriteLine("File Name: {0}", item.Name);
}

DriveInfo Sınıfı

DriveInfo sınıfı, dosya sistemindeki bir sürücünün bilgilerine ukaşmayı sağlar.

Özellikler: AvailableFreeSpace, DriveFormat, DriveType, IsReady, Name, RootDirectory, TotalFreeSpace, TotalSize, VolumeLabel

Metodlar: GetDrives(Sistemdeki bütün sürücüleri verir)

DriveType Enumerasyonu

Sürücünün olabileceği tipleri tutan bir temsili numaralandırmadır.

CDRom, Fixed, Network, NoRootDirectory, Ram, Removable, Unknown

Örnek:


DriveInfo[] drives = DriveInfo.GetDrives();

foreach (var item in drives)
{
    Console.WriteLine("Drive Name: {0}", item.Name);
    Console.WriteLine("Drive Type: {0}", item.DriveType);
}

Path Sınıfı

Path sınıfı dosya sistemindeki dosya yollarına erişmeyi ve gerekli işlemleri yapmayı sağlar.

Metodlar: ChangeExtension, Combine, GetDirectoryName, GetExtension, GetFileName, GetFileNameWithoutExtension, GetFullPath, GetPathRoot, GetRandomFilneName, GetTempFileName, GetTempPath, HasExtension, IsPathRooted

Örnek:

string targePath = @"c:\text.txt";

Console.WriteLine("Path       {0}", targePath);
Console.WriteLine("Extension: {0}", Path.GetExtension(targePath));

Console.WriteLine("Changed Extension as {0}", Path.ChangeExtension(targePath, "bak"));

 

FileSystemWatcher sınıfı

Bu sınıf dosya sisteminde istenen dizini dinlemeye yarar.  Yani dizinde bir dosya veya klasör olşturulduğunda, silindiğinde ya da değiştirildiğinde  bu olayları yakalamak mümkündür.

Özellikler: EnableRaisingEvents, Filter, IncludeSubdirectories, NotifyFilter, Path

Metodlar: WaitingForChanged

Olaylar: Changed, created, Deleted, Renamed

Örnek:


FileSystemWatcher watcher = new FileSystemWatcher(@"d:\");

watcher.EnableRaisingEvents = true;

watcher.Created += new FileSystemEventHandler(watcher_Changed);

watcher.Deleted += new FileSystemEventHandler(watcher_Changed);

Console.ReadLine();

Olay gerçekleştiğinde  çalışacak metod ise şu şekilde olmalıdır.


static void watcher_Changed(object sender,FileSystemEventArgs e)
{
     Console.WriteLine("Directory changed({0}): {1}", e.ChangeType, e.FullPath);
}

Umarım faydalı bir yazı olmuştur.

Kısaca Generic(Türe Özgü) Sınıflar

11 Ara

Generic tipler .Net 2.0 ile birlikte gelen yeniliklerden birisidir. Generic tipte yapılan bir tanımlama, bu tipin hangi tipler ile çalışabileceğini belirlemeye olanak sağlamaktadır. .Net platformunda generic tiplere örnek olarak List<T>, Nullable<T>, Dictionary<T,K> gibi tipleri verebiliriz. Bu tipler System.Collections.Generic ad uzayında barınmaktadır. Bunun yanında kendi generic  tiplerimizi tanımlamak da mümkündür.

Neden Generic Tipleri Kullanmalıyız
Generic tipleri kullanmamızın en temel sebeplerinden biri, nesnelerin Object türüne dönüştürülmesi(casting işlemi) veya Object türündeki nesnelerin istenen tipe çevrilmesi sorunudur. Yani generic kullanımlar sayesinde tip dönüştürme sorununu ortadan kaldırmaktır. Generic tiplerin iki önemli avantajı bulunmaktadır.

  • Runtime(Çalışma zamanı) Hataları: Object tip dönüşütürme işlemi sırasında oluşabilecek hataları derleyici anlayamamaktadır. Örneğin string tipindeki bir değişkeni object tipine dönüştürdüğümüzü varsayalım, daha sonra da bu object türünü int tipine dönüştürmeye çalıştığımızda derleme sırasında bir hata oluşmayacaktır. Ancak runtime esnasında bir hata oluşacaktır. Generic tiplerin kullanılması ise bu hataların derleme sırasında yakalanarak müdahale edilmesini sağlamaktadır. Ayrıca oluşturulan generic tiplerin hangi tipler ile çalışabileceğini de sınırlayabilmekteyiz.
  • Performans etkisi: Tip dönüştürme işlemleri işlemcinin zamanını almakta ve performansı olumsuz etkilemektedir. Generic tiplerde ise böyle bir durum söz konusu değildir. Çalışılacak türler başlangıçta belirlendiği için tip dönüşümüne gerek kalmamaktadır.

Örnek:


class ObjectTest
{

   public object T;
   public object K;

   public ObjectTest(object t, object k)
   {
      T = t;
      K = k;
   }
}

class GenericTest<T,K>
{
   public T t;
   public K k;

   public GenericTest(T t, K k)
   {
      this.t = t;
      this.k = k;
   }
}

Yukardaki örnekte ObjectTest sınıfı tip dönüşümlerini gerektirecek bir türü temsil etmekte, GenericTest sınıfı ise kullanılacak tip dönüşümüne gerek duymuyor. Bunu şu şekilde ispatlayabilirsiz.

static void Main(string[] args)
{
   ObjectTest obTest = new ObjectTest("Merhaba ", "dünya");
   Console.WriteLine((string)obTest.T + (string)obTest.K);

   GenericTest<string, string> genTest =
                  new GenericTest<string, string>("Merhaba ", "dünya");
   Console.WriteLine(genTest.t+ genTest.k);
 }

Yukarıda sınıfların kullanımı sırasında generic tip örneği başlangıçta iki adet string tipi ile çalışacağını belirlemeye izin veriyor. Bu yüzden tip dönüşümüne gerek kalmıyor.

Umarım faydalı bir yazı olmuştur.

Bu yazıyla ilgili çalışan bir uygulamanın kodlarını buradan bulabilirsiniz.

Referans Tipleri (Reference Types)

10 Ara

Referans tipleri .Net Framework platformunda çok kullanılan tiplerdir. Referans tipleri büyük bir  esnekliğe sahip olmakla beraber metodlarda kullanılırken çok iyi performas sağlar.

Referans tipleri stack bölgesinde dataların bulunduğu adresleri depolarlar. Pointer olarakta adlandırılabilir. Adreslerin işaret ettiği asıl veriler ise belleğin heap adı verilen bölgesinde depolanmaktadır. Çalışma zamanı (Runtime) garbage collection diye bilinen bir mekanizma sayesinde bellek yönetimini kontrol etmektedir. Garbage collection ise çöp toplayıcı bir mekanizmadır. Yani belleği periyodik olarak kontrol eder ve bellekte artık kullanılmayan öğeri yok eder.

Referans ve Değer Tiplerinin Karşılaştırılması

Bir referans tipi adres bilgisi barındırdığı için bir referans tipi değişkenini başka bir referans tip değişkenine atadığımızda değişkenin sadece adresi kopyalanmış olur. Yani veriler kopyalanmaz. Sadece iki değişkende aynı heap bölgesini işaret etmektedir.

Örnerk:

Struct Selection
 {
      public int val;
      public Selection(int Val)
      {
        val=Val;
      }

      public override string ToString()
      {
         return val.ToString();
      }
 }

Selection adında bir structure hazırladık ve aşağıdaki gibi iki Selection tipini kopyalamaya çalışalım.


 Selection s1 = new Selection(0);
 Selection s2= s1;
 s1.val+=1;
 s2.val+=2;
 Console.WriteLine("s1 = {0},s2 = {1}", s1, s2);

Bu örnekte çıktı olarak “s1=1, s2=2” sonucunu alırız. Bunun sebebi struct tipinin bir değer tipi olmasıdır. Eğer Selection yapısının tipini class olarak değiştirirsek çıktı olarak “s1=3, s2=3” sonucunu alırız. Yani Selection tipini değiştirmekle değer tipinden referans tipine geçirmiş oluruz.

Built-in Referans Tipleri

.Net Framework bünyesinde 2500 den fazla mevcut (built-in) referans tipi barınmaktadır. Bunlardan en çok kullanılanlar aşağıdaki tabloda verilmektedir.

Type Kullanım
System.Object Framework’ün en genel tipidir. Bütün tiplerde bulunan ToString, GetType, Equals gibi metodları  bünyesinde barındırır.
System.String Text şeklindeki verileri tutar.
System.Text.StringBuilder Dinamik text verilerini tutar.
System.Array Dizileri temsil eder.
System.IO.Stream Dosya, aygıt ve network ortamında kullanılır.
System.Exception Sistem ve uygulama bazındaki istisnaları yakalar.

String ve StringBuilder sınıfları

Bu sınıflar test verilerini tuttukları gibi tuttukları veriler üzerinde işlem yapabilme yeteneğine de sahiptir.

Örneğin System.String sınıfı bünyesinde birçok üye bulundurmaktadır.


string s = "this is some text to search";

s = s.Replace("search", "replace");

Console.WriteLine(s);

System.String sınıfının bir başka özelliği ise değiştirilemez olmasıdır. İyi ama bu ne demek? Bu şu anlama geliyor; çalışma zamanında(runtime) esnasında string tipinede bir değişkende herhangi bir değişiklik yapmak demek eski string yerine yeni bir string oluşturmak demektir.

Örnerk:


string s;
s = "wombat";       // "wombat"
s += " kangaroo";  // "wombat kangaroo"
s += " wallaby";     // "wombat kangaroo wallaby"
s += " koala";         // "wombat kangaroo wallaby koala"

Console.WriteLine(s);

Yukardaki örnekte saadece son stringin referansı bulunmaktadır. Yani önceki üç veri çöptoplama esnasında yok edilecektir. Bu tür geçici işlemlerden uzak durmak performans açısından önemlidir. Bu durumdan kaçınmak için birkaç yol vardır.

  • String sınıfının Contact, Join veya Format metodlarını kullanarak bir string ifadesine birden çok öğeyi eklemek mümkündür.
  • StringBuilder sınıfını kullanarakdinamik olarak string oluşturmak mümkündür.

StringBuilder sınıfını kullanmak en esnek yöntemdir. Çünkü birden fazla  ifadeyi birleştirebilen bir yapıya sahiptir. Varsayılan kurucu metodu 16 bayt uzunluğunda bir tampona sahiptir. İhtiyaç oldukça genişleyebilmektedir. İsenilen büyüklükte başlangıç boyutu ve maksimum boyutu belirlenebilmektedir.

Örnek:


System.Text.StringBuilder sb = new System.Text.StringBuilder(30);
sb.Append("wombat");  // string oluştur.
sb.Append(" kangaroo");
sb.Append(" wallaby");
sb.Append(" koala");
string s = sb.ToString();    // onucu bir string değişkenine aktar.

Console.WriteLine(s);

String sınıfının diğer bir önemli özelliği ise System.Object operatörlerinin aşırı yüklenmesidir. Aşağıdaki tabloda string sınıfının aşırı yüklenmiş operatörleri verilmektedir.

Operatör C# İşlevi
Ekleme + İki string değişkenini birleştirir.
Eşitlik == İki string değişkenin aynı ieriğe eşit olup olmadığını kontrol eder.
Eşitsizlik != Eşitsizliği kontrol eder.
Atama = String ifasesini diğer bir string ifadesine kopyalar.

Diziler

Diziler C# dilinde köşeli parantezler ile ifade edilmektedir. String tipinde olduğu gibi System.Array sınıfının da kendine özgü üyeleri bulunmaktadır. Bu üyeler dizi içindeki verilerle çalışmaya yarar. Örneğin bir dizinin verilerinin sıralanması için şu metodu kullanabiliriz:

Array.Sort(array);

Diziyi tanımlamak ve dizinin verilerine ulaşmak ise şu şekildedir.


int[] array = { 5, 81, 2, 62 };

Array.Sort(array);

Console.WriteLine("{0}, {1}, {2}", array[0], array[1], array[2]);

Streams

Stream tipleri disk üzerine veri yazıp okuk veya ağ üzerinden iletişim sağlamak için kullanılır. System.IO.Stream tipi tüm stream tipler için temel oluşturur. Aşağıdaki tabloda en çok kullanılan stream tipler listelenmektedir. Ağ akışları için kullanılan stream tipler System.Network.Sockets ad uzayında bulunmaktadır.

System.IO Tipleri Kullanımları
FileStream Dosya okuma ve yazma işlemleri.
MemoryStream Bellek okuma yazma işlemleri.
StreamReader Akışkan ortam verilerini okumak için kullanılır.
StreamWriter Akışkan ortamlara veri yazmak için kullanılır.

En basit tipler olan StreamReader ve StreamWriter text dosyası oluşturmamızı sağlar. Varsayılan kurucu metoda dosya adını girerek tek satırda dosyaya erişmek mümkündür. Dosya ile işlem bittiğinde Close metodu çağrılarak dosya kilidi kaldırılmalıdır. Aşağıda dosya yazma ve okuma işlemine bir örnek verilmektedir.


StreamWriter sw = new StreamWriter("text.txt");
sw.WriteLine("Hello, World!");
sw.Close();

 StreamReader sr = new StreamReader("text.txt");
Console.WriteLine(sr.ReadToEnd());
sr.Close();

İstisnalar (Exception)

Bir uygulamanın beklenmedik durumlarda normal çalışmasını kesmek için kullanılır. Örneğin, taşınabilir bir disk üzerindeki çok fazla veri içeren bir dosyadan okuma işlemi gerçekleştirirken diskin çıkarıldığında uygulama okuma işlemine devam edemeyecektir.

İstisnalar(Exceptions) bu gibi durumlarda uygulamanın tamamen sonlamasını engellemek, oluşan hatanın yakalanmasın sağlamak için kullanılır. Aşağıda buna uygun bir örnek verilmektedir.

try
 {
    StreamReader sr = new StreamReader(@"C:\test.text");
    Console.WriteLine(sr.ReadToEnd());
 }
 catch (Exception ex)
 {
   Console.WriteLine("Error reading file: " + ex.Message);
 }

Yukardaki örnekte bir hata oluşması durumunda, oluşan hata catch bloğu tarafından yakalanacaktır. Eğer bir hata oluşmazssa cacth bloğu atlanacaktır.

Temel sınıf olan Exception sınıfının yanında .Net platformunda, System.SystemException sınıfından türemiş yüzlerce istisna sınıfı bulunmaktadır. Ayrıca System.ApplicationException sınıfından türeterek kendi istisna sınıflarımızı da oluşturabilirz.

Birden fazla istisnanın olduğu durumlarda hataların farklı türlerine göre farklı yanıt verilir. Bu durumda birden fazla cache bloğu hataları en özelden en genele doğru sıralayarak oluşrurulur.

Hata yakalama mekanizması try ve catch bloğu yanında bride finally bloğu vardır. Finally bloğu try ve catch bloklarından sonra çalışır. Bunu şöyle bir örnekle açıklayabiliriz. Örneğin bir dosyayı okumak StreamReader için açtınız ve dosya kilitlendi. Okuma işlemi bitip Close metodu çalışana kadar dosya açık kalacaktır. Bu gibi durumlarda finally bloğunda Close metodu çağrılabilir.

StreamReader sr = new StreamReader("text.txt");

try
{
  Console.WriteLine(sr.ReadToEnd());
}
catch (Exception ex)
{
  Console.WriteLine("Error reading file: " + ex.Message);
}
finally
{
  sr.Close();
}

Yukarıdaki Finally bloğundan Try bloğu içindeki değişkenlere erişilemediği için StreamReader nesnesi Try bloğu dışına tanımlanmıştır.

Genelde basit değişken tanımlamaları dığında herşey try bloğu içinde olmalıdır. Hata yakalama işlemi sayesinde uygulamalar daha kullanışlı hale getirilebilmektedir. Ancak bu işlemin performansa olumsuz yönde etkisi olmaktadır.

Bu yazıyla ilgili çalışan bir uygulamanın kodlarını buradan bulabilirsiniz.

Kaynak: MCTS Self-Paced Training Kit: Microsoft .Net Framework 2.0 Application Development Faundation

Javascript ile Doğrulama Uyarısı

8 Ara

Microsoft .Net platformunda desktop veya silverlight ile uygulamalar yaparken kullanıcıya evet/hayır tarzı seçimleri yaptırmak gerekebiliyor. Bu seçimleri bir mesaj kutusu yardımıyla halletmek mümkün olabilmektedir. Ancak web ortamında sunucu tabanlı uygulamalarda bu tarz seçenekler olmadığından en uygun yöntem javascript nimetlerinden yararlanmak olacaktır.

Örneğin bir linke veya butona tıkladığımızda “Bunu yapmak istediğinizden emin misiniz?” gibi uyarılar  verdirmek isteyebiliriz. Aşağıdaki örnekte işleme devam etmek veya etmemek konusunda kararı verdirip ikinci adımı belirleyebileceğimiz bir örnek verilmiştir.


<html>
<head>
<script type="text/javascript">

    function ShowConfirm() {
        var confirmation = confirm("Emin misiniz?");
        if (confirmation) {
          alert("Kayıt Silinmiştir.");
        }
        return confirmation;
    };

</script>

</head>
<body>

<h1>Alert uygulaması</h1>

<a href="http://www.bayramucuncu.com"  onclick="return ShowConfirm();">KAYDI SİL</a>

</body>
</html>

Yukardaki örnekte Kaydı sil adında bir link bulunmakta ve linke tıklandığında kullanıcıya
emin olup olmadığı sorulmaktadır.

Umarım faydalı olmuştur herkese iyi çalışmalar.

Değer Tipleri (Value Types)

6 Ara

.Net framework platformunun en basit tipleri nümerik ve mantıksal (Boolean) olan değer tiplerdir. Değer tipleri bellekte her hangi biryerde referans tutmadan direkt olarak kendi verilerini tutarlar. Değer tiplerinin örnekleri(Instances) bellekte stack denilen bölgede tutulur. Stack bölgesindeki verileri runtime esnasında oluşturma, güncelleme ve silme işlemleri en az iş yükü ile hızlıca gerçekleşir.

Genel olarak üç çeşit değer tipi bulunmaktadır.

  • Built-in tipler. .Net Framework bünyesindeki tiplerdir.
  • User-defined tipler. Kullanıcıların tanımladığı tiplerdir.
  • Enumeration tipler. Enum tipleridir.

Bütün bu tipler System.Value temel tipinden türemiştir.

Built-In Değer Tipleri

Built-in değer tipleri .Net Framework ortamında bulunan ve başka tiplerden inşa edilmiş temel tiplerdir. Aşağıdaki tabloda en çok kullanılan nümerik tipler bellekte kapladıkları alanlara göre büyükten küçüğe sıralanmıştır. Bunlardan ilk altı tanesi tamsayı değerlerini, son üç tanesi ise real sayıları temsil etmek için kullanılan tiplerdir.

Tip Byte
System.Sbyte(Sbyte/sbyte) -128 ve 127
System.Byte(Byte/byte) 0 ve 255
System.Int16(Short/short) -32768 ve 32767
System.Int32(Integer/int) –2147483648 ve 2147483647
System.UInt32(UInteger/uint) 0 ve 4294967295
System.Int64(Long/long) –9223372036854775808 ve9223372036854775807
System.Single (Single/float) –3.402823E+38 ve3.402823E+38
System.Double(Double/double) –1.79769313486232E+308 ve1.79769313486232E+308
System.Decimal(Decimal/decimal) –79228162514264337593543950335 ve79228162514264337593543950335

Not: Çalışma zamanı(runtime) 32 bit integer (Int32 ve Uınt32) tiplerini optimize eder. Bu yüzden sayaç(counter) ve sık erişilen değişkenler bu tiplerde olmalıdır. Örneğin döngülerde kullanılan sayaç değişkenleri int tipinde olması performansı arttırır. Floating point işlemlerinde ise Double tipi en etkili tiptir. Çünkü bu tip işlemler donanımlar tarafından optimize edilir.

Nümerik tiplerin yanında nümerik olmayan built-in veri tipleri de aşağıda verilemktedir.

Tip Byte
System.Char(Char/char) 2
System.Bolean (Boolean/bool) 4
System.IntPtr
System.DateTime (Date/date) 8

Bu tiplerin yanında Framework’te 300 den fazla tip mevcuttur. Ancak burada en sık kullanılan tipler verilmiştir. Değer tipleri arasında atama işlemi yapıldığında, veri bir değişkenden diğerine kopyalanmakta ve  iki ayrı stack bölgesinde depolanmaktadır.

Değer tipleri genellikle basit türleri temsil etmesine rağmen yine de nesneler(Object) olarak işleve görmektedir. Yani nesnelere(Object) ait metodları değer tipleri üzerinden çağırabiliriz. Örneğin en sık kullanılan metod olan ToString()  metodu değer tiplerine ait örneklerden erişilebilir. .Net Framework’te bütün neslere System.Object sınıfından türemiştir.bu sayede bütün tiplerin ortak bir noktası olmuştur.

Değer Tiplerinin Tanımlanması

Bir değer tipini kullanmaya başlamadan önce tanımlanması gerekmektedir. Değer tipleri gizli bir kurucu metoda sahiptir. Bu yüzden tanımlama esnasında sınıflarda kullanıldığı gibi  New anahtar kelimesinin kullanılmasına gerek yoktur. Mevcut kurucu metod, tanımlanan değişken örneğine başlangıç değeri olarak (Null, 0 veya False) gibi değerleri otomatik olarak atar. Ancak yinde oluşturulan değişkenlere başlangıç değerlerinin verilmesinde fayda vardır.

Örnek:

bool b = false;

Not: C# büyük harf ve küçük harfe duyarlı bir dildir.

Bazı durumlarda değişkenlerin null olması gerektiği durumlar oluşabilir. Örneğin bir formdan Evet/Hayır şeklinde bir cevap almak istendiğinde kullanıcı seçeneği işaretlemedğinde de null değer saklanması gerekebilir. Bu durumlarda değişkeni Nullable olarak tanımlayabiliriz. .Net 2.0 ile gelen bu özellik sayesinde aşağıdaki gibi tanımlamalar yapabiliriz.

Örnek:

Nullable<bool> b = null;

//Veya

bool? B = bull;

Nullable değişkenlerin HasValue ve Value isimli iki özelliği bulunmaktadır. Bu sayede değişkenin değer içerip içermediği kontrol edilebilmektedir.

User-Defined (Kullanıcı Tanımlı) Tipler

Kullanıcı tanımlı değer tipleri Stracture olarak bilinen ve struct olarak tanımlanan tiplerdir. Diğer değer tipleri gibi struct tipi örnekleri de belleğin stack bölgesinde tutulur. Kendi verilerin tutarlar. Diğer yönleriyle sınıflarla hemen hemen aynı davranırlar.

Stracture tipleri diğer tiplerin kombinasyonundan oluşurlar ve bu da ilgili verilere kolay erişmeyi sağlar. Bunu en basit örneklerinden biri System.Drawing.Point yapısıdır. Bünyesinde int türünden X ve Y adında iki özellik barındırır. Bu özellikler noktanın koordinatlarını verir.

Örnek:

System.Drawing.Point p = new System.Drawing.Point(); //Nokta tanımlanıyor

p.Offset(-1,-1);  //Köşegen yönünde kaydırılıyor.

Kendi struct tipimizi de tanımlayabiliriz.

Örnek:

struct Cycle
{
  int val, min, max;
  public Cycle(int min, int max);
  {
    val=min;
    min=min;
    max=max;
  }

…….

}

Yukardaki Cycle örneğini değer tipinden referans tipine çevirmek son derece kolay. Yapılması gereken sadece struct yerine class yazmaktır. Bu durumda heap bölgesine 12 byte (her değişken için 4 byte) tahsis edilecektir.

İşlevsellik benzer olsa da structure’lar  sınıflardan çok daha etkili sonuç verir. Uzman görüşü olarak 16 byte’tan küçük veriler için performansın yüksek olmasını istiyorsanız class yerine struct kullanmalısınız.

Enumeration Tipleri

Enumeration tipleri kodun rahat okunabilmesini sağlamak amacıyla geliştirilen semboilk tiplerdir. Geliştirme aşamasında sınırlı seçenekler sunmak amacıyla tanımlanırlar.

Örnek:

enum Titler{
    Mr, Ms, Mrs, Dr
}

Kaynak: MCTS Self-Paced Training Kit: Microsoft .Net Framework 2.0 Application Development Faundation