SORU
20 Kasım 2008, PERŞEMBE


Modifiye Kapatma erişim (2)

Bu Access to Modified Closure soru bir uzantısıdır. Ben sadece eğer aşağıdaki aslında üretim kullanımı için yeterince güvenli olup olmadığını doğrulamak için.

List<string> lists = new List<string>();
//Code to retrieve lists from DB	
foreach (string list in lists)
{
	Button btn = new Button();
	btn.Click  = new EventHandler(delegate { MessageBox.Show(list); });
}

Ben sadece başlangıç başına yukarıda bir kez çalıştırın. Şimdilik iyi iş gibi görünüyor. Jon bazı durumda mantığa aykırı sonuç ifade ettiği gibi. Burada dikkat etmeniz gereken şey nedir? Eğer liste birden fazla kez çalıştırmak olursa sorun olacak mı?

CEVAP
20 Kasım 2008, PERŞEMBE


Önce C# 5, re-değişken bildiriniçindebu dosyalarda grup - aksi paylaşıldığını ve tüm işleyicileri son dizeyi kullanır:

foreach (string list in lists)
{
    string tmp = list;
    Button btn = new Button();
    btn.Click  = new EventHandler(delegate { MessageBox.Show(tmp); });
}

Önemli ölçüde, C# 5 itibaren bu durum değişti unutmayın, veözellikle foreach durumundaartık bunu yapmana gerek yok: söz konusu kod beklendiği gibi. işe yarar

Bu değişiklik olmadan çalışmıyor göstermek için, aşağıdakileri göz önünde bulundurun:

string[] names = { "Fred", "Barney", "Betty", "Wilma" };
using (Form form = new Form())
{
    foreach (string name in names)
    {
        Button btn = new Button();
        btn.Text = name;
        btn.Click  = delegate
        {
            MessageBox.Show(form, name);
        };
        btn.Dock = DockStyle.Top;
        form.Controls.Add(btn);
    }
    Application.Run(form);
}

Yukarıdaki çalıştırınC# 5 öncedüğmeleri "Wilma" dört kez gösterdi. tıklayarak her butonun adını gösterir, ancak , ve,

Bu dil spec (ECMA 334 v4, 15.8.4) (C önce# 5) tanımlar çünkü

foreach (V v in x)embedded-statementdaha sonra genişletilmiş

{
    E e = ((C)(x)).GetEnumerator();
    try {
        V v;
         while (e.MoveNext()) {
            v = (V)(T)e.Current;
             embedded-statement
        }
    }
    finally {
        … // Dispose e
    }
}

14 ** değişken 15**) ilan olduğunu unutmayındışarıdadöngü. Yakalanan değişkenleri kurallar bu kadar, listenin tüm yineleme yakalanan değişken yuvasını paylaşacak.

C# 5 itibaren bu değişti: değişken (v), kapsamlı bir göz atalımiçindedöngü. Şartname bir başvuru yok, ama temel olarak yorumlamışlardır

{
    E e = ((C)(x)).GetEnumerator();
    try {
        while (e.MoveNext()) {
            V v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally {
        … // Dispose e
    }
}

Re aboneliği; eğer aktif olarak isimsiz bir işleyici çıkmak istiyorsanız, olay işleyicisi kendisini yakalamak için:

EventHandler foo = delegate {...code...};
obj.SomeEvent  = foo;
...
obj.SomeEvent -= foo;

Eğer isterseniz, aynı şekilde, sadece bir kez olay işleyicisi (Yük vb):

EventHandler bar = null; // necessary for "definite assignment"
bar = delegate {
  // ... code
  obj.SomeEvent -= bar;
};
obj.SomeEvent  = bar;

Bu şimdi kendini aboneliği ;-p

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Edgar flores

    Edgar flores

    7 HAZİRAN 2006
  • Alexey - servant of Christ

    Alexey - ser

    15 EYLÜL 2007