C# İpuçları

Tekrardan merhabalar,

Bu derste, C#’ta kod yazarken faydalandığım çeşitli özelliklerden bahsedeceğim. Bu özelliklerden bazıları, benim vereceğim örneklerden çok daha geniş kapsamlılar. İlginizi çekenleri ayrıca araştırabilir veya sorularınız olursa sorabilirsiniz. Hızlıca derse başlayalım!

  • Sadece getter’ı olan ve o getter’ındaki kod tek satırdan oluşan bir property’i expression body formatında yazmak:
// Önce
public bool KarakterCanliMi
{
	get { return Saglik > 0; }
}

// Sonra
public bool KarakterCanliMi => Saglik > 0;
  • Tek satırdan oluşan fonksiyonları expression body formatında yazmak (bunu her zaman yapmıyorum; değişiklik kodda sırıtacaksa fonksiyonu normal şekilde yazıyorum):
// Önce
public void YokEt()
{
	Destroy(gameObject);
}

// Sonra
public void YokEt() => Destroy(gameObject);
  • new ile yeni bir instance’ını oluşturduğumuz objenin türü belliyse, constructor’ı kısaltmak:
// Önce
Vector3 v3 = new Vector3(3, 5, 10);
List<int> liste = new List<int>(16);
Dictionary<int, GameObject> dict = new Dictionary<int, GameObject>();
KarakteriIsinla(new Vector2(3, 5));

// Sonra
Vector3 v3 = new(3, 5, 10);
List<int> liste = new(16);
Dictionary<int, GameObject> dict = new();
KarakteriIsinla(new(3, 5));
// Önce
GameObject sonObje = array[array.Length - 1];
GameObject sondanIkinciObje = array[array.Length - 2];

// Sonra
GameObject sonObje = array[^1];
GameObject sondanIkinciObje = array[^2];
  • Bir fonksiyon içerisinde başka bir fonksiyon tanımlamak (local function):
// Önce
void GaleriyiGuncelle()
{
	List<string> resimler = new();
	List<string> videolar = new();
	KlasoruKontrolEt(Application.persistentDataPath, resimler, videolar);
	KlasoruKontrolEt(Application.temporaryCachePath, resimler, videolar);
}

void KlasoruKontrolEt(string klasor, List<string> resimler, List<string> videolar)
{
	foreach (string konum in Directory.GetFiles(klasor))
	{
		if (konum.EndsWith(".png") || konum.EndsWith(".jpg"))
			resimler.Add(konum);
		else if (konum.EndsWith(".mp4"))
			videolar.Add(konum);
	}
}

// Sonra
void GaleriyiGuncelle()
{
	List<string> resimler = new();
	List<string> videolar = new();
	KlasoruKontrolEt(Application.persistentDataPath);
	KlasoruKontrolEt(Application.temporaryCachePath);
	
	void KlasoruKontrolEt(string klasor)
	{
		foreach (string konum in Directory.GetFiles(klasor))
		{
			if (konum.EndsWith(".png") || konum.EndsWith(".jpg"))
				resimler.Add(konum);
			else if (konum.EndsWith(".mp4"))
				videolar.Add(konum);
		}
	}
}

  • Bir string’in içerisine çeşitli değişkenlerin değerini gömmek için string interpolation kullanmak:
// Önce
Debug.Log("Karakter " + karakter.Ad + "'in " + karakter.Saglik + " sağlığı kaldı");

// Sonra
Debug.Log($"Karakter {karakter.Ad}'in {karakter.Saglik} sağlığı kaldı");
  • Bir objenin türünü is operatörü ile kontrol ederken, eğer obje gerçekten o türdeyse, aynı satırda onu yeni bir değişkene atamak (pattern matching):
public void DegeriKaydet(string key, object deger)
{
	if (deger is int sayi)
		PlayerPrefs.SetInt(key, sayi);
	else if (deger is string stringDeger)
		PlayerPrefs.SetString(key, stringDeger);
	else
		Debug.LogError("Bilinmeyen değer: " + deger);
}
  • Bir obje belli bir türde değilse diye kontrol etmek için is not pattern matching kullanmak:
public void KaraktereHasarVer(Karakter karakter, int hasar)
{
	// Eğer dost ateşi (friendly fire) kapalı ise ve karakter düşman değilse, bir şey yapma
	if (friendlyFireKapali && karakter is not Dusman)
		return;
	
	karakter.Saglik -= hasar;
}
  • Bir fonksiyonun out parametresinin değişkenini inline olarak tanımlamak:
// Önce
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
	...

// Sonra
if (Physics.Raycast(ray, out RaycastHit hit))
  • Bir fonksiyonun out parametresinin döndürdüğü objeyi kullanmayacaksak, onu ‘_‘ ile discard etmek:
// Önce
public bool KarakterZemindeMi()
{
	RaycastHit hit;
	return Physics.Raycast(transform.position, Vector3.down, out hit);
}

// Sonra
public bool KarakterZemindeMi()
{
	return Physics.Raycast(transform.position, Vector3.down, out _);
}
  • Tuple’lar kullanarak birden çok değeri aynı anda depolamak/döndürmek:
void EnYakinDusmanlariYokEt()
{
	List<(GameObject dusman, float mesafe)> menzildekiDusmanlar = MenzildekiDusmanlariBul();
	 
	// Düşmanları mesafeye göre küçükten büyüğe sırala
	menzildekiDusmanlar.Sort((e1, e2) => e1.mesafe.CompareTo(e2.mesafe));
	 
	// En yakındaki 3 düşmanı yok et
	for (int i = 0; i < 3 && i < menzildekiDusmanlar.Count; i++)
		Destroy(menzildekiDusmanlar[i].dusman);
}
 
List<(GameObject dusman, float mesafe)>  MenzildekiDusmanlariBul()
{
	List<(GameObject, float)> sonuc = new();
	for (int i = 0; i < dusmanlar.Count; i++)
	{
		float mesafe = Vector3.Distance(dusmanlar[i].transform.position, transform.position);
		if (mesafe < 5)
			sonuc.Add((dusmanlar[i], mesafe));
	}
	 
	return sonuc;
}
  • Tuple’lar kullanarak iki değeri swap etmek:
// Önce
int temp = sayi1;
sayi1 = sayi2;
sayi2 = temp;

// Sonra
(sayi1, sayi2) = (sayi2, sayi1);
  • Bir fonksiyona aynı türden birden çok objeyi params ile kolayca parametre olarak verebilmek:
public void DusmanlaraHasarVer(int, hasar, params Dusman[] dusmanlar)
{
	for (int i = 0; i < dusmanlar.Length; i++)
		dusmanlar[i].Saglik -= hasar;
}

DusmanlaraHasarVer(10, dusman);
DusmanlaraHasarVer(10, dusman1, dusman2);
DusmanlaraHasarVer(10, dusman1, dusman2, dusman3);
  • Koda gömülü büyük bir sayıyı rahatça okuyabilmek için bindeliklere ayırmak:
// Önce
sayininOnMilyonKati = sayi * 10000000;

// Sonra
sayininOnMilyonKati = sayi * 10_000_000;
List<int> liste = null;

...

// Önce
if (liste == null)
	liste = new();

// Sonra
liste ??= new();
// Önce
public class ServisDTO
{
	public string id;
	public int deger;
}

string json = JsonConvert.SerializeObject(new ServisDTO()
{
	id = karakter.id,
	deger = 10
});

// Sonra
string json = JsonConvert.SerializeObject(new
{
	id = karakter.id,
	deger = 10
});
  • try-catch’e when ile koşullar eklemek:
// Önce
try
{
	...
}
catch (ArgumentException e)
{
	if (e.ParamName == "xParametresi")
		throw;
	
	...
}

// Sonra
try
{
	...
}
catch (ArgumentException e) when (e.ParamName != "xParametresi")
{
	...
}
  • Logical pattern matching kullanarak if koşullarını sadeleştirmek (eğer bir değişkeni başka bir değişkenle kıyaslıyorsanız çalışmaz):
// Önce
if (intDegisken >= 0 && intDegisken <= 10)

// Sonra
if (intDegisken is >= 0 and <= 10)

Başka derslerde görüşmek dileğiyle!

MEHMET SÖNMEZ için bir cevap yazın Cevabı iptal et


4 yanıt

  1. seyf Avatar
    seyf

    bu tarz orta-ileri düzey c# dersleri bekliyoruz hocam.

  2. MEHMET SÖNMEZ Avatar
    MEHMET SÖNMEZ

    C# sunduğu kolaylıkları anlattığınız için teşekkür ederim

  3. MT Avatar

    Üstadım artık Bolt Cursor, Replit vb. içerikler de bekliyoruz.

    1. yasirkula Avatar

      Ara ara kullandığım ChatGPT haricinde sektörden bihaberim 😀 Bu konuda ders muhtemelen yazmam. Önümüzdeki süreçte Unity Behaviour neymiş diye bakıp DOTS’ta da kendimi geliştirmeyi düşünüyorum. Belki yeri gelince onlarla ilgili ders yazarım.