C#‘da Gerekli Fonksiyon Çağrılarını Zorunlu Kılma
Problem: Kontrol Edilmeyen Fonksiyon Çağrıları
C#‘da, durum döndüren fonksiyonlar oluşturmak oldukça yaygındır ve bu, geliştiricilerin operasyonların başarı veya başarısızlığını izlemelerine yardımcı olur. Ancak, bazı geliştiricilerin bu döndürülen durumları tamamen göz ardı etmesi yaygın bir tuzaktır. Eğer uygun hata yönetimi uygulanmazsa, bu istenmeyen sonuçlara yol açabilir.
Örneğin, bir işlemin başarılı olup olmadığı veya yürütme sırasında sorunlar yaşanıp yaşanmadığı hakkında bilgi içerebilecek bir Status
sınıfını düşünelim:
Status MyFunction()
{
if(...) // bir şey kötü
return new Status(false, "Bir şeyler ters gitti");
else
return new Status(true, "Tamam");
}
Beklenti, MyFunction
‘ın tüm çağrıcılarının döndürülen durumu kontrol etmesidir:
Status myStatus = MyFunction();
if (!myStatus.IsOK())
// işle, bir mesaj göster,...
Bununla birlikte, bazı çağrıcılar durumu kontrol etmeyi tembellik ederek göz ardı edebilir:
// Döndürülen durumu göz ardı etme
MyFunction(); // fonksiyonu çağır ve döndürülen Status'u göz ardı et
Bu Önlenebilir Mi?
Bu, önemli bir soruyu gündeme getiriyor: Her çağrıcının döndürülen durumu kontrol etmesini nasıl sağlayabiliriz? C++‘da, nesnenin yaşam döngüsünün sonunda durumu doğrulamak için bir yıkıcı kullanılabilir. Ancak, C#‘da, yıkıcılar çöp toplayıcısının belirsiz doğası nedeniyle genellikle hoş karşılanmaz.
Çözüm: Gerekli Fonksiyon Çağrıları için Delegeler Kullanma
C#‘da bir metodun döndürülen değerini çağrılmasını veya kontrol edilmesini zorunlu kılmanın doğrudan bir yolu olmasa da, yenilikçi bir çözüm delegeler kullanmayı içerir. Bu teknik yalnızca bir değer döndürmez; bunun yerine, çağrıcının döndürülen durumu açıkça işleme almasını bir geri çağırma mekanizması aracılığıyla zorunlu kılar.
Örnek Uygulama
Delegeler kullanarak basit bir uygulamaya bakalım:
using System;
public class Example
{
public class Toy
{
private bool inCupboard = false;
public void Play() { Console.WriteLine("Oynuyor."); }
public void PutAway() { inCupboard = true; }
public bool IsInCupboard { get { return inCupboard; } }
}
public delegate void ToyUseCallback(Toy toy);
public class Parent
{
public static void RequestToy(ToyUseCallback callback)
{
Toy toy = new Toy();
callback(toy);
if (!toy.IsInCupboard)
{
throw new Exception("Oyuncağını dolaba kaldırmadın!");
}
}
}
public class Child
{
public static void Play()
{
Parent.RequestToy(delegate(Toy toy)
{
toy.Play();
// Ah! Oyuncağı kaldırmayı unuttum!
});
}
}
public static void Main()
{
Child.Play();
Console.ReadLine();
}
}
Kodun Açıklaması
Bu örnekte, Parent.RequestToy
çağrıldığında, Toy
nesnesi ile işlemler gerçekleştirecek bir geri çağırma fonksiyonu bekler. Geri çağırmayı gerçekleştirdikten sonra, oyuncağın kaldırılıp kaldırılmadığını kontrol eder:
- Geri çağırma
toy.PutAway()
‘ı çağırmazsa, bir istisna fırlatılır. Bu, çağrıcınınToy
‘u kullanımı sonrasında ele alması gerektiğini zorunlu kılar, böylece gerekli takip işlemlerinin gerçekleşmesi sağlanır. - Bu yöntem, çağrıcının durumu kontrol etmeyi hatırlayacağının garantisini vermez, ancak işlemin önemini artıracak şekilde bir yapı zorunlu kılar.
Sonuç
C#‘da döndürülen değerlere yönelik kontrolleri C++ kadar katı bir şekilde zorunlu kılmak mümkün olmayabilir, ancak delegeleri kullanarak ileriye dönük bir işlem gerekliliğini etkili bir şekilde ileten bir desen oluşturabiliriz; bu da kodun güvenilirliğini artırır. Bu deseni kullanmak, hem fonksiyon sonuçlarının uygun bir şekilde ele alınmasına yardımcı olur hem de programlama pratiğinizi düzenli ve temiz tutar.
Bu yaklaşımı uygulayarak, kodunuzu kullanan geliştiricilerin zorunlu kontrolleri kolayca atlayamayacaklarından emin oluruz. Biraz alışılmadık görünebilir, ancak hata yönetimi konusunda bir hesap verebilirlik kültürü oluşturmak için faydalı bir yol sunar.