Arşiv

Etiketlenen yazılar method

C# string sınıfı ve özellikleri

.Net string sınıfı uygulamalarımızda sıklıkla kullandığımız sınıflardan biridir.

.Net 1.1 versiyonundan itibaren gelişme göstermesine rağmen, hala bazı fonksiyonlarının eksik olduğunu veya tam anlamıyla kullanılmadığını düşünüyoum.

Bu makalemde, string sınıfının çok bilinmeyen veya çok kullanılmayan özelliklerine ve methodlarına değinmeye çalışacağım.

String değişkeni tekrar eden karakterler ile doldurmak

String değişkeni tekrar eden karakterler ile doldurmak için, String sınıfının constructor’ını kullanmak gerekir.

Örneğin, bir string değişkeni 50 adet nokta (.) karakteri ile doldurmak istiyorsak;

string degisken = new string('.', 50);

String değişkenin boş olduğunu kontrol etmek

String değişkenin değer içerip içermediğini belirlemek için string.Empty ve boş tırnaklar (“”) ile karşılaştırmamız gerekir.

if (degisken != null && degisken != "")
{
}

Alternatif olarak bu iki karşılaştırmayı yapmak yerine, .Net 2.0 ile gelen string.IsNullOrEmpty static fonksiyonunu kullanabiliriz;

if (!string.IsNullOrEmpty(degisken))
{
}

String.Empty ve boş tırnaklar (“”) arasındaki fark

İnternette çeşitli sitelerde, string.Empty ve boş tırnaklar (“”) arasında seçim yapmak için yazılmış makalelere rastlayabilirsiniz.

Aslında yapılan onlarca test gösteriyor ki, performans açısından bakıldığında string.Empty ve boş tırnaklar (“”) arasında önemsenmeyecek kadar küçük bir fark vardır.

Yapılan testler milyarlarca string değişken üzerinde yapılmasına rağmen ortaya çıkan fark göz ardı edilebilecek kadar düşük seviyededir.

String değişkenin içeriğini ters çevirmek

Bir string değişkenin içeriğini ters çevirmek için çeşitli algoritmalara internet üzerinden ulaşabilir veya kendi algoritmanızı geliştirebilirsiniz.

Kodun temizliği, hız, Unicode karakter setleri ile sorunsuz çalışabilmesi açısından benim en çok kullandığım yöntem şudur;

public static string Reverse(this string s)
{
	char[] charArray = s.ToCharArray();
	Array.Reverse(charArray);
	return new string(charArray);
}

String karşılaştırma

String değişkenin değeri null olabileceği için, karşılaştırma operatörünü (==) kullanmaktan kaçınmamız gerekir.

Bunun yerine String sınıfının static Compare method’unu kullanmamız daha doğrudur.

Static Compare method’u sayesinde null referans’ları doğru şekilde karşılaştırabilir, büyük-küçük harf duyarlılığını yoksayabilir, farklı Culture’daki değerleri karşılaştırabiliriz.

if (String.Compare(degisken1, degisken2, true) == 0)
{
}

Büyük-Küçük harf duyarlılığı olmayan IndexOf

String sınıfının IndexOf method’u büyük-küçük harf duyarlıdır. Büyük-Küçük harf duyarlılığı olmadan IndexOf method’unu kullanmak istiyorsak, System.Globalization namespace’inde yeralan CompareInfo sınıfı’nın IndexOf method’unu kullanabiliriz;

using System.Globalization;

string degisken1 = "Uygulamalarımızın olmazsa olmaz unsurları değişkenlerdir";
string degisken2 = "OLMAZ";

CompareInfo karsilastirma = CultureInfo.InvariantCulture.CompareInfo;
int i = karsilastirma.IndexOf(degisken1, degisken2, CompareOptions.IgnoreCase);

string ve String farkı

MSDN’deki String sınıfı ile alakalı bir sayfadan alıntı;

“The keyword string is simply an alias for the predefined class System.String.” – C# Language Specification 4.2.3

Türkçesi;

“string anahtar kelimesi basitçe, System.String sınıfının takma adıdır.” – C# Language Specification 4.2.3

C# ile bilgisayarınızdaki diskleri listelemek

25 Ağustos 2010 Yorum yapılmamış

.Net 2.0 ile birlikte System.IO namespace’inde bulunan birçok eksiklik giderilmiştir. Özellikle Windows’un Dosya Sistemine erişmek için yeni sınıflar ve methodlar eklenmiştir.

DriveInfo sınıfında yapılan bir geliştirme sayesinde sistemde kurulu disklere erişebilir, disklerin tiplerini sorgulayabilir, kapasitelerini ve boş alan miktarını öğrenebiliriz.

Örneğin, sistemdeki diskleri listelemek için;

DriveInfo[] diskler = DriveInfo.GetDrives();
foreach (DriveInfo disk in diskler)
{
    string diskAdi = disk.IsReady ? String.Format(" - {0}", disk.VolumeLabel) : null;
    Console.WriteLine( "{0} - {1}{2}", disk.Name, disk.DriveType, diskAdi);
}

C:\ – Fixed – Sistem
D:\ – Fixed – Dosyalar
E:\ – CDRom
F:\ – CDRom
G:\ – Removable
H:\ – Removable
T:\ – Fixed – Temp
Y:\ – Fixed – Yedekler

IsReady property’si sayesinde disk’in o anda sistemde kullanılabilir olup olmadığını kontrol ediyoruz. Örneğin, içinde CD olmayan CD okuyucu için, disk’in etiketini almaya çalışmıyoruz. Uygulamamızın hata ile karşılaşmaması için, bu dikkat etmemiz gereken bir nokta.

Name ve DriveType özellikleri, diskin hazır olduğu durumlardan bağımsız olarak, her zaman kullanılabilir durumdadır.

C# siz olsanız hangisini yazardınız?

27 Temmuz 2010 3 yorum

İnternette gezerken şöyle bir kod parçasına rastladım;

public void ShowPanelWindow(bool isVisible)
{
	Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed;
}

public void ShowBusy(bool isBusy)
{
	BusyIndicator.ShowIsBusy = isBusy;
}

Bu kodu yazan kişi, eğer yukarıdaki kodu şimdi yazsaydım şöyle yazardım demiş ve aşağıdaki kod parçasını yazmış;

public void HidePanelWindow()
{
	Visibility = Visibility.Collapsed;
}

public void ShowPanelWindow()
{
	Visibility = Visibility.Visible;
}

public void LookBusy()
{
	BusyIndicator.ShowIsBusy = true;
}

public void StopLookingBusy()
{
	BusyIndicator.ShowIsBusy = false;
}

Bu iki kodu okuduktan sonra, kendi kendime sordum ve ben de ikinci tarz yaklaşımı kullanırdım.

Peki siz olsanız hangi tarz kodu tercih ederdiniz?

Kısa kod mu? Kendini anlatan kod mu?

Ayın ilk ve son gününü bulmak için Extension Method

Özellikle raporlama uygulamalarında, aylık dönemlere ait sorgulama yapılırken ilgili ayın ilk ve son günlerinin bilinmesi gerekir.

C# uygulamamızda, yazacağımız basit iki tane extension method ile ayın ilk ve son günlerini bulan kodu basitleştirebiliriz.

public static class ExtensionMethods
{
	public static DateTime AyinIlkGunu(this DateTime dt)
	{
		return new DateTime(dt.Year, dt.Month, 1);
	}

	public static DateTime AyinSonGunu(this DateTime dt)
	{
		return dt.AyinIlkGunu().AddMonths(1).AddDays(-1);
	}
}

Extension Method‘ların kullanımı;

static void Main(string[] args)
{
	DateTime BuAy_BaslangicTarihi = DateTime.Now.AyinIlkGunu();
	DateTime BuAy_BitisTarihi = DateTime.Now.AyinSonGunu();

	DateTime GecenAy_BaslangicTarihi = DateTime.Now.AddMonths(-1).AyinIlkGunu();
	DateTime GecenAy_BitisTarihi = DateTime.Now.AddMonths(-1).AyinSonGunu();
}

Örnek kodun tamamı;

using System;

class Program
{
	static void Main(string[] args)
	{
		DateTime BuAy_BaslangicTarihi = DateTime.Now.AyinIlkGunu();
		DateTime BuAy_BitisTarihi = DateTime.Now.AyinSonGunu();

		DateTime GecenAy_BaslangicTarihi = DateTime.Now.AddMonths(-1).AyinIlkGunu();
		DateTime GecenAy_BitisTarihi = DateTime.Now.AddMonths(-1).AyinSonGunu();
  }
}

public static class ExtensionMethods
{
	public static DateTime AyinIlkGunu(this DateTime dt)
	{
		return new DateTime(dt.Year, dt.Month, 1);
	}

	public static DateTime AyinSonGunu(this DateTime dt)
	{
		return dt.AyinIlkGunu().AddMonths(1).AddDays(-1);
	}
}

Dizi oluşturma ve sıralama

12 Mart 2010 5 yorum

C# ile en basit dizi tanımlama yöntemi, değişken tipinin sonuna [] karakterlerini eklemektir.

Örnek :

int[] TekSayilar = { 3, 1, 9, 5, 7 };

string[] Ogrenciler = { "Engin", "Ahmet", "Mehmet", "Ali", "Veli" };

Dizileri sıralamak için, Array sınıfının static Sort() methodunu kullanabiliriz;

Array.Sort(TekSayilar);

Array.Sort(Ogrenciler);

Şimdi TekSayilar ve Ogrenciler dizilerindeki elemanları ekrana yazdırırsak;

foreach (int Sayi in TekSayilar)
	Console.WriteLine(Sayi);

foreach (string Ogrenci in Ogrenciler)
	Console.WriteLine(Ogrenci);

Dizilerdeki elemanların sıralanmış olduklarını görürüz.

XNA ile Pong oyunu yazalım – 2

XNA ile Pong oyunu yazalım – 1 yazıma bu yazı ile devam ediyorum.

XNA ile ekrana yazı yazdırmak için öncelikle Content projesi içerisinde bir spritefont dosyası oluşturmalıyız.

Pong projesi için ben Arial.spritefont ismini verdiğim dosyayı oluşturdum, “yorum satırları kaldırılmış halini” aşağıdaki gibi düzenledim;

<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
	<Asset Type="Graphics:FontDescription">
		<FontName>Arial</FontName>
		<Size>16</Size>
		<Spacing>0</Spacing>
		<UseKerning>true</UseKerning>
		<Style>Regular</Style>
		<CharacterRegions>
			<CharacterRegion>
				<Start>&#32;</Start>
				<End>&#126;</End>
			</CharacterRegion>
		</CharacterRegions>
	</Asset>
</XnaContent>

Gördüğünüz gibi, font dosyası aslında font’un özelliklerini yazdığımız bir Xml dosyası.

GameLoop sınıfının değişkenlerine Arial font dosyamızı yükleyeceğimiz değişkeni de ekleyelim;

SpriteFont Arial;

LoadContent() method’unda Arial.spritefont dosyasını Arial değişkenine yükleyelim;

Arial = Content.Load<SpriteFont>("Arial");

Şimdi Draw() method‘una aşağıdaki kodları ekleyerek, oyuncuların skorlarını ekrana yazdıralım;

spriteBatch.DrawString(Arial, "Oyuncu 1 : " + Oyuncu1Skor, new Vector2((float)(PENCERE_GENISLIK * 0.05), 30), Color.Yellow);
spriteBatch.DrawString(Arial, "Oyuncu 2 : " + Oyuncu2Skor, new Vector2((float)(PENCERE_GENISLIK * 0.80), 30), Color.Yellow);

Bu kod parçası ile, spriteBatch değişkeninde yeralan DrawString() method’unu kullandık. DrawString() method’unun parametrelerine bakacak olursak;

  • Birinci parametre olarak, spritefont tipinde bir değişken alır
  • İkinci parametre, ekrana yazdırmak istediğimiz yazıdır
  • Üçüncü parametre olarak Vector2 tipinde yazıyı nereye yazacağımız bilgisini ister
  • Son olarak, yazının rengini verdiğimiz dördüncü parametre vardır

Biz, Pong oyununda ilk oyuncunun skorunu ekranın %5 kadar içine, ikinci oyuncunun skorunu ise ekranın %20 kadar içine yazdırdık.

Gelelim, oyunda ses çıkartmaya;

Öncelikle wav formatında iki ses dosyasını Content içerisine sürükleyip bırakalım.

Class seviyesindeki değişkenlere iki tane daha ekleyelim;

SoundEffectInstance ArkaplanSes;
SoundEffectInstance SkorSes;

LoadContent() method’unda bu değişkenlerin değerlerini atayalım;

ArkaplanSes = Content.Load<SoundEffect>("Pong").CreateInstance();
SkorSes = Content.Load<SoundEffect>("recycle").CreateInstance();

Gördüğünüz gibi, SoundEffectInstance tipinde iki değişken tanımladık. Bu değişkenlere Content içindeki ses dosyalarını yüklerken, SoundEffect tipinin CreateInstance() method‘unu kullandık.

Böylece ses değişkenlerimiz kullanıma hazır hale geldi.

LoadContent() method’una aşağıdaki kodları da ekleyerek, arkaplanda çalacak ses değişkeninin sesini %20 oranına düşürelim ve loop olmasını sağlayalım (Böylece ses dosyasının sonuna geldiğinde başa dönüp çalmaya devam edecek).

Son olarak Play() methodu ile, ses dosyasını çalmaya başlayalım;

ArkaplanSes.Volume = 0.2f;
ArkaplanSes.IsLooped = true;
ArkaplanSes.Play();

Update() method’unda oyuncuların skor kazandığı kodlara aşağıdaki satırı da ekleyelim;

SkorSes.Play();

Böylece oyuncular skor yaptıkça, SkorSes değişkeninde yüklü olan ses dosyası çalınacak.

İşte Pong oyunundan ekran görüntüsü. Oyunun kaynak kodlarını buradan indirebilirsiniz.

XNA Pong oyunun bitmiş hali

Kalıtımı engellemek (sealed anahtar kelimesi)

Yazdığınız bir sınıftan kalıtım yoluyla başka sınıflar üretilmesini engellemek istiyor olabilirsiniz.

Yapmanız gereken sınıfınızı sealed anahtar kelimesi ile “mühürlemek” olmalıdır. Böylece sınıfınızdan yeni sınıflar türetilemeyecektir.

sealed class AnaSinif
{
// Sınıf üyeleri
}

AnaSinif class‘ımız sealed olduğu için, yeni sınıf türetilirken base class olamayacaktır;

class TuretilmisSinif : AnaSinif
{
// Derleme zamanında hata oluşur (compile-time error)
}

Not : struct’lar her zaman sealed ile mühürlenmiş gibi davranırlar. struct’lar kalıtım (inheritance) desteklemez

Tüm sınıfın kalıtım yoluyla aktarılmasını engellemek yerine, tek bir method’un override edilmesini engellemek istiyor olabilirsiniz.

Bu durumda yapmanız gereken, sadece ilgili method‘u sealed ile “mühürlemek” olmalıdır;

class AnaSinif
{
	public virtual void Goster()
	{
	}
}

class TuretilmisSinif : AnaSinif
{
// Bu kodda problem yok
// AnaSinif'tan gelen Goster() method'unu override eder
// Aynı zamanda sealed ile "mühürler"
	public sealed override void Goster()
	{
	}
}

class TekrarTuretilmisSinif : TuretilmisSinif
{
// Bu kod derlenmez. Hata oluşur
// TuretilmisSinif class'ında Goster() method'u sealed anahtar kelimesi ile "mühürlenmişti"
	public override void Goster()
	{
	}
}

Dosya veya Dizin isimlendirirken kullanmamanız gereken karakterler

System.IO namespace‘inde yer alan Path class‘ının

GetInvalidFileNameChars()

GetInvalidPathChars()

methodlarını kullanarak dosya veya dizin isimlendirirken kullanmamanız gereken karakterleri bulabilirsiniz.

Her iki method’dan da geriye char[] döner.

MSDN’de şuradaki makaleden GetInvalidFileNameChars() methodu ile ilgili ayrıntılı bilgiye ulaşabilirsiniz.

MSDN’de şuradaki makaleden GetInvalidPathChars() methodu ile ilgili ayrıntılı bilgiye ulaşabilirsiniz.

virtual olmayan method’ları override etmek

Base class‘ta tanımlanmış bir method‘u override etmemiz gerekiyor. Fakat method virtual yazılmamışsa, override edilemez. Türetilmiş class‘ta base class‘taki virtual olmayan method’u nasıl override edebiliriz?

Türetilmiş class’ta base class’taki method’u override etmek yerine new anahtar kelimesi ile baştan yazabiliriz. Böylece virtual yazılmamış ve dolayısıyla override edilemeyecek method’ları “bir çeşitoverride etmiş oluruz.

class Base
{
	public virtual void VirtualGoster()
	{
		Console.WriteLine(“Base.VirtualGoster”);
	}

	public void Goster()
	{
		Console.WriteLine(“Base.Goster”);
	}
}

class Derived : Base
{
	public override void VirtualGoster()
	{
		Console.WriteLine(“Derived.VirtualGoster”);
	}

	public new void Goster()
	{
		Console.WriteLine(“Derived.Goster”);
	}
}

class Program
{
	static void Main(string[] args)
	{
		Base base = new Derived();
		base.VirtualGoster();
		base.Goster();

		Console.WriteLine();

		Derived derived = new Derived();
		derived.VirtualGoster();
		derived.Goster();
	}
}

Çıktı :
Derived.VirtualGoster
Base.Goster
Derived.VirtualGoster
Derived.Goster

LINQ ile Dosya Sisteminde Sorgulama Yapmak

Yazdığımız uygulamalarda dosya sisteminde arama yapmaya ihtiyaç duyabiliriz. Bu durumda genelde döngüler yazarız. Peki LINQ kullanamaz mıyız? Üzerinde biraz çalıştıktan ve araştırma yaptıktan sonra, aşağıdaki kodu elde ettim;

private IEnumerable<FileInfo> DosyaListesi(DirectoryInfo KokDizin, string Uzanti, string DosyaAdiParcasi)
{
	foreach (var f in KokDizin.GetFiles().Where(Dosya => Dosya.Extension == Uzanti && Dosya.Name.Contains(DosyaAdiParcasi)))
		yield return f;

	foreach (DirectoryInfo d in KokDizin.GetDirectories())
		foreach (var f in DosyaListesi(d, Uzanti, DosyaAdiParcasi))
			yield return f;
}

Gördüğünüz gibi fonksiyon, parametre olarak aramaya başlanacak kök dizini, arama yapılacak dosyanın uzantısını ve dosya isminde bir parçayı alıyor, geriye FileInfo sınıfında liste döndürüyor.

İlk foreach döngüsünde kök dizinde parametre ile alınmış kriterlere göre arama yapılıyor ve yield anahtar kelimesi ile, bulunan her sonuç dönüş kümesine ekleniyor.

İkinci (ve üçüncü) foreach döngülerinde ise, recursive (kendini tekrarlamalı) olarak DosyaListesi() fonksiyonu kendi kendisini çağırarak, arama işlemini alt klasörlerde de yapıyor.

C# String’i Title Case’e (Kelimelerin Baş Harfleri Büyük Gerisi Küçük) Çevirme

25 Ocak 2010 6 yorum

.Net Framework içerisinde string.ToUpper() ve string.ToLower() fonksiyonlarını kullanarak string değişkenin içeriğini BÜYÜK ve küçük harfe çevirebiliyoruz.

Metni Upper Case (Tümü Büyük Harfler) ve Lower Case (Tümü Küçük Harfler) formatlamak haricinde Title Case (Kelimelerin Baş Harfleri Büyük Gerisi Küçük) çevirmek yaygın kullanılan başka bir formattır.

string sınıfına bir Extension Method yazarak bu özelliğe sahip olmasını sağlayabiliriz. Extension Method‘u yazarken bilmemiz gereken ilk şey, ToTitleCase() method’unun TextInfo sınıfında yer aldığıdır. TextInfo sınıfına CultureInfo sınıfının CurrentCulture özelliğinden ulaşabiliriz.

public static class ExtensionManager
{
	public static string ToTitleCase(this string Text)
	{
		return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Text);
	}
}

Artık projemiz içerisinde herhangi bir yerde string değişkenimizin ToTitleCase() method’unu kullanabiliriz.

private void frmMain_Load(object sender, EventArgs e)
{
	string AdSoyad = "engin polat".ToTitleCase();
}

Yukarıdaki kod parçası çalıştığı zaman, AdSoyad değişkeninin içeriği Engin Polat olacaktır.

Not : CultureInfo sınıfının CurrentCulture özelliğinden TextInfo sınıfının özelliklerine eriştiğimiz için, bilgisayarınızda kullandığınız dile göre sonuç farklılık gösterebilir.

C# Try-Catch-Finally Kod Bloğu Hakkında

24 Ocak 2010 2 yorum

Geçen aylarda BilgeAdam‘da bir öğrencimin sorduğu soru geldi aklıma. Soru aslında çok basit, fakat farkettim ki, internette bu konu ile ilgili pek kaynak yok. Bari kendim yazayım dedim. Soru şu;

Bir method'dan geriye true/false değer döndürmem lazım.

Method içerisine yazdığım kodları try-catch-finally blokları içerisine almam gerekiyor.

Eğer try içerisinde hata oluşmazsa, geriye true değer döndüreceğim. Hata oluşur ve kod catch bloğuna girerse false değer döndüreceğim.

Ama finally kod bloğunda yapmam gereken işler var. (Açık bağlantıları kapatmak, vs.)

Eğer try-catch içerisinde return ifadesini kullanırsam, finally bloğundaki kod çalışır mı?

Sorunun doğru cevabı için; Devamını oku…

C# İsimsiz Tipler – Anonymous Types

Sadece bir method içerisinde kullanacağınız basit class‘lara kaç defa ihtiyaç duydunuz? Böyle bir class’a her ihtiyaç duyduğunuzda yapmanız gereken, yeni bir class oluşturup, bütün tanımlama kodlarını (private alanlar, public alanlar, vs.) yazmaktır.

C# dili, İsimsiz Tip (Anonymous Type) tanımlamaya izin veriyor. Üstelik, private ve public öğelerin oluşturulmasını ve yönetilmesini C# dilinin kendisi üstleniyor.

public class HataLogla()
{
	var Hata = new { Mesaj = "Hata Mesajının Kendisi", Tarih = DateTime.Now, Yer = "XClass.YMethod" };
	var Kullanici = new { Id = 42, AdSoyad = "Engin Polat", Yonetici = "Ali Veli" };

	string Loglanacak = string.Format("Hata Mesajı: {0}\nTarih: {1} {2}\nHatanın Oluştuğu Yer: {3}\n\nKullanıcıId: {4}\nKullanıcı Adı: {5}\nYöneticisi: {6}", Hata.Mesaj, Hata.ToShortDateString(), Hata.Tarih.ToLongTimeString(), Hata.Yer, Kullanici.Id, Kullanici.AdSoyad, Kullanici.Yonetici);

	File.WriteAllText(Loglanacak, @"C:\Log\Log.txt");

	MessageBox.Show(Hata.Mesaj, Hata.Tarih);
}

Yukarıdaki kodda yer alan Hata ve Kullanici değişkenlerinin tipleri, derleme zamanında derleyici tarafından otomatik oluşturulur. Eğer method‘un içerisine aşağıdaki kodları eklersek;

MessageBox.Show("Hata değişkeninin tipi : " + Hata.GetType().ToString());
MessageBox.Show("Kullanici değişkeninin tipi : " + Kullanici.GetType().ToString());

Mesaj kutularında şu değerleri görürüz;

Hata değişkeninin tipi : <>f_AnonymousType0’3[System.String,System.DateTime,System.String]
Kullanici değişkeninin tipi : <>f_AnonymousType0’3[System.Int32,System.String,System.String]

Farkettiğiniz gibi, böyle bir tip oluşturmaya çalışırsak, derleme zamanında hata alırız, ama C# derleyicisi bizim için bu tipleri oluşturuyor.

Değişkenin tipini veremeyeceğimiz için, C# diline var anahtar kelimesi eklenmiştir.

var anahtar kelimesi sayesinde, değişkenin tipi atandığı değerden otomatik olarak çözümleniyor.

İsimsiz Tipler (Anonymous Types) IDisposable interface’ini uygulamadığı için, Disposable olamazlar.

Eğer yukarıdaki örneği geleneksel kodlama teknikleri ile yazacak olsaydık;

public class HataBilgi
{
	private string _Mesaj = string.Empty;
	private DateTime _Tarih = DateTime.Now;
	private string _Yer = string.Empty;

	public string Mesaj
	{
		get
		{
			return _Mesaj;
		}
		set
		{
			_Mesaj = value;
		}
	}

	public DateTime Tarih
	{
		get
		{
			return _Tarih;
		}
		set
		{
			_Tarih = value;
		}
	}

	public string Yer
	{
		get
		{
			return _Yer;
		}
		set
		{
			_Yer = value;
		}
	}

	public HataBilgi(string Mesaj, DateTime Tarih, string Yer)
	{
		this.Mesaj = Mesaj;
		this.Tarih = Tarih;
		this.Yer = Yer;
	}
}

public class KullaniciBilgi
{
	private int _Id = 0;
	private string _AdSoyad = string.Empty;
	private string _Yonetici = string.Empty;

	public int Id
	{
		get
		{
			return _Id;
		}
		set
		{
			_Id = value;
		}
	}

	public string AdSoyad
	{
		get
		{
			return _AdSoyad;
		}
		set
		{
			_AdSoyad = value;
		}
	}

	public string Yonetici
	{
		get
		{
			return _Yonetici;
		}
		set
		{
			_Yonetici = value;
		}
	}

	public KullaniciBilgi(int Id, string AdSoyad, string Yonetici)
	{
		this.Id = Id;
		this.AdSoyad = AdSoyad;
		this.Yonetici = Yonetici;
	}
}

public class HataLoglama
{
	HataBilgi Hata = new HataBilgi("Hata Mesajının Kendisi", DateTime.Now, "XClass.YMethod");
	KullaniciBilgi Kullanici = new KullaniciBilgi(42, "Engin Polat", "Ali Veli");

	string Loglanacak = string.Format("Hata Mesajı: {0}\nTarih: {1} {2}\nHatanın Oluştuğu Yer: {3}\n\nKullanıcıId: {4}\nKullanıcı Adı: {5}\nYöneticisi: {6}", Hata.Mesaj, Hata.ToShortDateString(), Hata.Tarih.ToLongTimeString(), Hata.Yer, Kullanici.Id, Kullanici.AdSoyad, Kullanici.Yonetici);

	File.WriteAllText(Loglanacak, @"C:\Log\Log.txt");

	MessageBox.Show(Hata.Mesaj, Hata.Tarih);
}

İsimsiz Tip yeteneklerini kullanarak yazdığımızda ise;

public class HataLogla()
{
	var Hata = new { Mesaj = "Hata Mesajının Kendisi", Tarih = DateTime.Now, Yer = "XClass.YMethod" };
	var Kullanici = new { Id = 42, AdSoyad = "Engin Polat", Yonetici = "Ali Veli" };

	string Loglanacak = string.Format("Hata Mesajı: {0}\nTarih: {1} {2}\nHatanın Oluştuğu Yer: {3}\n\nKullanıcıId: {4}\nKullanıcı Adı: {5}\nYöneticisi: {6}", Hata.Mesaj, Hata.ToShortDateString(), Hata.Tarih.ToLongTimeString(), Hata.Yer, Kullanici.Id, Kullanici.AdSoyad, Kullanici.Yonetici);

	File.WriteAllText(Loglanacak, @"C:\Log\Log.txt");

	MessageBox.Show(Hata.Mesaj, Hata.Tarih);
}

Aradaki fark açıkça ortada!

C# 3.0 Object Initializer Özelliği

C# 3.0 object initialize etmek için kodda kısaltma sağlayacak bir yenilik sunuyor. Hemen hergün aşağıdaki gibi kod yazmamız gerekmez mi?

Personel UygulamaGelistirici = new Personel();
UygulamaGelistirici.Id = 42;
UygulamaGelistirici.AdSoyad = "Engin Polat";
UygulamaGelistirici.Birim = "NTV - Yeni Medya";

Personel sınıfından yeni bir örnek oluşturduktan sonra, sınıfın özelliklerinden ihtiyacımız olanlara atamalar yapmaya başlarız.

Eğer Personel sınıfının constructor‘ı olsaydı ve bu özelliklerin atamalarını yapsaydı, tek bir satırda, hem Personel sınıfının yeni bir örneğini UygulamaGelistirici değişkenine oluşturmuş, hem de bazı özelliklerin değerlerini atamış olabilirdik.

Fakat, Personel sınıfının constructor‘ını yazamadığımız durumlarda veya constructor‘da parametreler ile almak için çok fazla özellik olduğu durumlarda bu yöntemi kullanamayız.

C# 3.0 ile birlikte Object Initializer denilen yeni bir kodlama tekniği tanıtıldı.

Hemen yukarıdaki örneği bu teknik ile yazalım;

Personel UygulamaGelistirici = new Personel() { Id = 42, AdSoyad = "Engin Polat", Birim = "NTV - Yeni Medya" };

Gördüğünüz gibi, kodlama bizim için kolaylaşıyor.

Object Initializer içerisinde sadece özelliklere atama yapabiliyoruz, method çağrımı vs. yapılamıyor.

Eğer sınıfın özellikleri başka sınıflardan örnekler istiyorsa, Object Initializer nasıl yazabiliriz? Aşağıdaki gibi yazabiliriz;

VeritabaniSorgulayici dbSorgu = new VeritabaniSorgulayici() {
	Connection = new SqlConnection("..ConnectionString.."),
	Command = new SqlCommand("..Sorgu..")
};

C# Obsolete Attribute

Yaklaşık olarak .Net Framework içerisinde binlerce class ve binlerce class içerisinde milyonlarca method vardır.

Her yeni .Net Framework versiyonunda bu class‘ların ve method‘ların bir kısmı yeni yöntemler / yeni teknikler ile baştan yazılıyor.

Bazen bu değişiklikler o kadar büyük oluyor ki, ilgili class veya method yeni bir isimle baştan yazılıyor ve eskisinin artık kullanılmaması öneriliyor.

Önceki Framework versiyonlarında yanlış konumlandırdıkları class veya method‘ları taşıdıkları durumlarda da aynı durum geçerli.

Geriye yönelik uyumluluktan dolayı, kullanılmaması önerilen class veya method‘lar üç versiyon daha yerinde durmaya devam eder.

Ama derleme zamanında uygulama geliştiriciye, ilgili class veya method‘un Obsolete olduğunu bildirir ve kodunu güncellemesini ister.

Bu özellik Obsolete Attribute sayesinde sağlanır.

Eğer biz de yazdığımız projelerimizde çeşitli class veya method’ları Obsolete yapmak istersek, aşağıdaki kodda gözüktüğü gibi yapabiliriz;

[Obsolete]
public class EskimisClass
{
	///
}

veya

[Obsolete("Bu method v4.5 versiyonundan itibaren kaldırılacak, lütfen yerine Ntv.YeniMedya.Veritabani sınıfında bulunan Baglan() methodunu kullanın. Ayrıntılı bilgi için http://www.xyz.com/Baglan sayfasına bakabilirsiniz")]
public void VeritabaniBaglan()
{
	///
}

Yukarıdaki kodda bulunan VeritabaniBaglan() method’unu kullanırken ve projemizi derlerken aşağıdaki ekranlar ile karşılaşırız;

Obsolete Method

Obsolete Method Error

C# Partial Method Desteği

C# 3.0 ile gelen partial keyword’u sayesinde partial class tanımlayabiliyoruz.

partial keyword’unun pek bilinmeyen bir kullanım alanı ise method‘lardır.

partial class tanımlayabildiğimiz gibi partial method‘da tanımlayabiliyoruz.

partial class‘ları tanımlamamızdaki en büyük fayda, kod üreticiler olmuştur. partial method tanımlamanın güzelliği de işte burada. Bir kod üreticisi ile otomatik olarak kod ürettirirken, partial method‘lar ürettirebiliriz.

Eğer üretilmiş partial method‘u uygulamazsanız, ilgili partial method‘u çağıran kod parçaları hata vermiyor.

Basitçe, uygulanmamış partial method çağrıları derleme (compile) sırasında yok sayılıyor.

Ama partial method‘lar için bazı kısıtlamalar ve kurallar var;

  • partial method’ların geri dönüş tipi herzaman void olmalıdır
  • partial method’lar out parametreler alamazlar, ama ref parametreler alabilirler
  • partial method’lar extern olamazlar
  • partial method’lar erişim belirleyici alamazlar, çünkü herzaman private erişim belirleyicisine sahiptirler
  • partial method’lar virtual olamazlar
  • partial method’lar static olabilir
  • partial method’lar generic olabilir
  • partial method’lara delegate bağlanamaz, çünkü partial method’un çalışma zamanında (runtime) var olacağı garanti değildir

Bu bilgilerden sonra örnek bir class yazalım;

public partial class DataAccessLayer
{
	partial void ResetConnection();
}

public partial class DataAccessLayer
{
	partial void ResetConnection()
	{
		///Connection'ı resetleyen kod
	}

	public void Reset()
	{
		ResetConnection();
	}
}

Gördüğünüz gibi, Reset() isminde public bir method yazmam gerekti. Çünkü, ResetConnection() method‘u partial olduğu için private erişim belirleyicisine sahip.

Eğer yukarıdaki kodun exe/dll dosyasına ILDASM tool’u bakarsak, DataAccessLayer.ResetConnection() private method’unu ve Reset() method‘u içerisinde bu method’u çağıran kod parçasını görürüz.

Eğer ResetConnection() method’unu uyguladığımız kod parçasını sildikten sonra, ILDASM ile bakarsak, DataAccessLayer.ResetConnection() private method’unun bulunmadığını ve Reset() method’unda bu method’u çağıran kod parçası olmadığını görürüz.

Böylece çalışma zamanı hatası almayız.

C# ile Google PageRank Bulma

23 Aralık 2009 1 yorum

Google‘ın PageRank uygulaması, web sitelerinin Google tarafından önemini bulmakta kullanılan bir algoritmadır.

Wikipedia’daki şu adresten, PageRank algoritması ile ilgili ayrıntılı bilgiye erişebilirsiniz.

Siz de sitenizin PageRank değerini http://www.prchecker.info adresinden bulabilirsiniz.

Yazacağımız uygulama ile, sitenizin Google PageRank değerini programatik olarak buldurabileceğiz.

Google sitelerin PageRank değerlerini, http://toolbarqueries.google.com/search adresine gönderilen sorgulara cevap olarak verebiliyor. Fakat sonuç alabilmemiz için bu adrese doğru parametreleri vermemiz gerekiyor, aksi halde HTTP403 : Forbidden hatası alıyoruz.

Parametreler:

  • features=Rank
  • client=navclient-auto
  • q=info:{adres}
  • ch={checksum}

Checksum bilgisini hesaplamak için Google’ın yayınladığı bir algoritma var. Uygulamamızda, bu algoritmayı C# ile yazacağız.

Yukarıdaki resimde görünen arayüzü hazırladıktan sonra, projemize GooglePageRank isminde static class ekliyoruz.

GooglePageRank static class’ı üç tane static method’dan oluşuyor.

private static void Mix(ref uint a, ref uint b, ref uint c)
{
	a -= b;
	a -= c;
	a ^= c >> 13;
	b -= c;
	b -= a;
	b ^= a << 8;
	c -= a;
	c -= b;
	c ^= b >> 13;
	a -= b;
	a -= c;
	a ^= c >> 12;
	b -= c;
	b -= a;
	b ^= a << 16;
	c -= a;
	c -= b;
	c ^= b >> 5;
	a -= b;
	a -= c;
	a ^= c >> 3;
	b -= c;
	b -= a;
	b ^= a << 10;
	c -= a;
	c -= b;
	c ^= b >> 15;
}
private static string GoogleChecksum(string url)
{
	uint GoogleMagic = 0xE6359A60;

	uint a, b;
	uint c = GoogleMagic;

	a = b = 0x9E3779B9;

	int k = 0;
	int length = url.Length;

	while (length >= 12)
	{
		a += (uint)(url[k + 0] + (url[k + 1] << 8) + (url[k + 2] << 16) + (url[k + 3] << 24));
		b += (uint)(url[k + 4] + (url[k + 5] << 8) + (url[k + 6] << 16) + (url[k + 7] << 24));
		c += (uint)(url[k + 8] + (url[k + 9] << 8) + (url[k + 10] << 16) + (url[k + 11] << 24));

		Mix(ref a, ref b, ref c);

		k += 12;
		length -= 12;
	}

	c += (uint)url.Length;

	switch (length)
	{
		case 11:
			c += (uint)(url[k + 10] << 24);
			goto case 10;
		case 10:
			c += (uint)(url[k + 9] << 16);
			goto case 9;
		case 9:
			c += (uint)(url[k + 8] << 8);
			goto case 8;
		case 8:
			b += (uint)(url[k + 7] << 24);
			goto case 7;
		case 7:
			b += (uint)(url[k + 6] << 16);
			goto case 6;
		case 6:
			b += (uint)(url[k + 5] << 8);
			goto case 5;
		case 5:
			b += (uint)(url[k + 4]);
			goto case 4;
		case 4:
			a += (uint)(url[k + 3] << 24);
			goto case 3;
		case 3:
			a += (uint)(url[k + 2] << 16);
			goto case 2;
		case 2:
			a += (uint)(url[k + 1] << 8);
			goto case 1;
		case 1:
			a += (uint)(url[k + 0]);
			break;
		default:
			break;
	}

	Mix(ref a, ref b, ref c);

	return string.Format("6{0}", c);
}
public static string PageRankHesapla(string adres)
{
	string checkSum = GoogleChecksum("info:" + adres);
	string url = "http://toolbarqueries.google.com/search?client=navclient-auto&ch=" + checkSum + "&features=Rank&q=info:" + adres;

	try
	{
		WebRequest request = WebRequest.Create(url);
		WebResponse response = request.GetResponse();

		StreamReader reader = new StreamReader(response.GetResponseStream());
		string data = reader.ReadToEnd();

		reader.Close();
		response.Close();

		if (data.IndexOf(':') != -1)
			data = data.Substring(data.LastIndexOf(':') + 1);

		return data;
	}
	catch (Exception)
	{
		return "-1";
	}
}

Şimdi yapmamız gereken, Butonun Click olayında, GooglePageRank static class’ının PageRankHesapla method’unu çağırmak ve dönen değeri Label’da göstermek.

Uygulamanın çalışır halini bu adresten indirebilirsiniz.