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);
newile 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));
- Array’in veya List’in son elemanına index operatörü ile erişme:
// Ö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ü
isoperatö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 notpattern 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
outparametresinin 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
outparametresinin 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;
- Bir objenin değeri null ise, ona aynı satırda değer vermek (null-coalescing operator):
List<int> liste = null;
...
// Önce
if (liste == null)
liste = new();
// Sonra
liste ??= new();
- Anonymous class’lar kullanarak, boş yere servis DTO class’ları oluşturmaktan kaçınmak:
// Ö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!