Eric Lippert'in cevabında belirttiği belirli bir noktayı ayrıntılandırmak ve kimsenin hiç değinmediği belirli bir olaya dikkat çekmek istiyorum. Eric dedi:
[...] bir atama hemen hemen her zaman bir kayıt defterinde atanmış olan değeri geride bırakır.
Atamanın her zaman sol operandımıza atamaya çalıştığımız değeri geride bırakacağını söylemek isterim. Sadece "neredeyse her zaman" değil. Ancak bilmiyorum çünkü bu konuyu belgelerde yorumlanmış olarak bulamadım. Teorik olarak "geride bırakmak" ve sol işleneni yeniden değerlendirmek için çok etkili uygulanan bir prosedür olabilir, ancak verimli mi?
Bu konudaki yanıtlarda şimdiye kadar oluşturulmuş tüm örnekler için 'Etkili' evet. Ancak get ve set erişimcilerini kullanan özellikler ve dizinleyiciler söz konusu olduğunda verimli mi? Bir şey değil. Bu kodu düşünün:
class Test
{
public bool MyProperty { get { return true; } set { ; } }
}
Burada, özel bir değişken için sarmalayıcı bile olmayan bir özelliğimiz var. Ne zaman çağrılsa, yerine geri dönecek, değerini belirlemeye çalıştığı zaman hiçbir şey yapmayacak. Dolayısıyla, bu mülk değerlendirildiği her zaman, doğru olacaktır. Bakalım ne olacak:
Test test = new Test();
if ((test.MyProperty = false) == true)
Console.WriteLine("Please print this text.");
else
Console.WriteLine("Unexpected!!");
Tahmin et ne basar? Yazdırır Unexpected!!
. Görünüşe göre, set erişimcisi gerçekten çağrılıyor ve bu hiçbir şey yapmıyor. Ancak bundan sonra, erişimci hiçbir zaman çağrılmaz. Görev, mülkümüze atamaya false
çalıştığımız değeri geride bırakıyor . Ve bu false
değer, if ifadesinin değerlendirdiği şeydir.
Bu konuyu araştırmamı sağlayan gerçek dünya örneğiyle bitireceğim . List<string>
Bir sınıfımın özel değişken olarak sahip olduğu bir koleksiyon ( ) için uygun bir sarmalayıcı olan bir indeksleyici yaptım .
Dizin oluşturucuya gönderilen parametre, koleksiyonumda bir değer olarak ele alınacak bir dizeydi. Get erişimcisi, bu değer listede mevcut olsa da olmasa da doğru veya yanlış döndürür. Böylece get erişimcisi, List<T>.Contains
yöntemi kullanmanın başka bir yoluydu .
Dizinleyicinin set erişimcisi, argüman olarak bir dizeyle çağrıldıysa ve doğru işlenen bir bool ise true
, o parametreyi listeye eklerdi. Ancak erişimciye aynı parametre gönderilmişse ve doğru işlenen bir bool ise false
, onun yerine öğeyi listeden silerdi. Böylece set erişimcisi, hem List<T>.Add
ve hem de için uygun bir alternatif olarak kullanıldı List<T>.Remove
.
Ağ geçidi olarak uygulanan kendi mantığımla listeyi saran düzgün ve kompakt bir "API" ye sahip olduğumu düşündüm. Yalnızca bir indeksleyicinin yardımıyla, birkaç tuş vuruşuyla birçok şey yapabilirim. Örneğin, listeme nasıl bir değer eklemeyi deneyebilirim ve onun içinde olduğunu nasıl doğrulayabilirim? Bunun gerekli olan tek kod satırı olduğunu sanıyordum:
if (myObject["stringValue"] = true)
; // Set operation succeeded..!
Ancak daha önceki örneğimin gösterdiği gibi, değerin gerçekten listede olup olmadığını görmesi gereken get erişimcisi çağrılmadı bile. true
Değeri her zaman arkasında etkili şekilde get erişimcisine uygulanan etmişti ne olursa olsun mantığı yok bırakıldı.