C # Delegelerinin gerçek dünya kullanımı [kapalı]


16

C # delegelerini kavramsal olarak anladığımı düşünüyorum, ancak faydalı olabilecekleri gerçek bir dünya örneği bulmak için mücadele ediyorum. C # delegelerinin gerçek uygulamalarda nasıl kullanıldığını ve etrafta dolaşmanızı sağlayan sorunları açıklayan bazı cevaplar verebilir misiniz?


2
.NET çerçevesindeki hemen hemen her sınıf bazı olayları ortaya koyar, işte böyle. Bu sadece bir iş birimini kapsüllemenin bir yoludur. Örneğin, C'de genel bir ikili ağaç yapısı uyguladığınızı varsayalım. Ağacınızı sipariş etmenin tek yolu, sıralamanın nasıl yapılacağını bilen bir işlev işaretçisi parametre olarak almak olacaktır.
Ed S.

Yanıtlar:


16

GUI kodu, düğme tıklamaları, pencere hareketleri gibi olayları işlemek için temsilciler kullanır. Temsilciyi kullanmak, olay gerçekleştiğinde çağrılan bir işleve sahip olmanızı sağlar. Bir örnek, verileri kaydeden bir işlevi arabirimdeki "Kaydet" düğmesine bağlamak olabilir. Düğme tıklandığında veri kaydeden işlevi yürütecek şekilde ayarlanır. GUI programlamasında faydalıdır, çünkü tüm programınız kullanıcının bir şey yapmasını bekleyebilir ve ilk önce ne yapacaklarını bilmenin bir yolu yoktur. Temsilci kullanmak, programınızın işlevselliğinin kullanıcı arabirimine, kullanıcının işleri istediği şekilde yapabileceği şekilde bağlanmasına olanak tanır.


2
++ Haklısın, ama yine de nefret ediyorum :-) çok yıllar önce bunun yerine geldim .
Mike Dunlavey

12

Linq kullanan Func<T>ve Action<T>tüm parametre olarak yerde delege.

Bunlar lambda ifadelerini parametre olarak kullanmanızı ve parametre listesinin bir parçası olarak gerçekleştirilecek eylemi tanımlamanızı sağlar.


12

Gözlemci Deseni'ni kullanan hemen hemen her şey delegeleri uygular.

Açıklamayı okuyun ve muhtemelen bunları kullanacağınız bazı senaryolar hayal edeceksiniz. GUI olay işleme yaygın bir örnektir.


+1, Strateji modeli gerçekten delegelerin parladığı yerdir, yani bazı yöntemlerin bir şeyler yaptığı bir sınıfınız vardır, ancak bir şeyin birbirinin yerine geçmesini ve doğrudan bağımlılık yapmadan ergo delegelerini olmasını istiyorsunuz. Olayların delegelerle aynı ihtiyacı karşıladığını unutmayın, fark, bazı dönüş değerlerine tepki vermeniz gerektiğinde delegeleri kullanmanızdır, oysa sadece olayları tetiklersiniz ve ne olacaksa.
Homde

9

Delegeler asenkron programlamada kanlı yararlıdır.

Eşzamansız olarak iş yapan ve geri arama yapan bir sınıfınız var. Temsilci yöntemini geri çağırma üzerine çağırabilirsiniz - ve sınıf uygulamanız temsilci yönteminizde açıklanan mantığı yapar.


9

Delegeler özellikle orta modeldeki delik için bir çözüm olarak kullanışlıdır . Esasen, bir dizi talimatın içine benzersiz bir talimat kümesi sarmak istediğiniz birçok durum vardır. Benzersiz bitin öncesi ve sonrası talimatların durumu paylaşması gerekiyorsa özellikle zordur. Delegelerle, bir temsilciyi bir işleve geçirebilirsiniz. İşlev önce biti yürütür, temsilci yürütür ve sonra biti yürütür.


5

Fortran ve C gibi OOP olmayan dillerin "eski günlerinde", bir altyordamın bir işleve işaret eden bir argüman almasını sağlamak son derece yararlı oldu. Örneğin, qsortişlev kullanıcı tarafından sağlanan bir karşılaştırma işleviyle çalışır. Sıradan diferansiyel denklemleri çözmek veya fonksiyonları optimize etmek için çok sayıda alt rutin vardır ve hepsi fonksiyon işaretlerini argüman olarak alır.

Pencereleme sistemlerinde her türlü geri arama aynı modeli izler.

Lisp'te, ilk günlerde bile, "işlevsel bir argüman" veya FUNARG adı verilen bir şey vardı, bu sadece bir işlev değildi, aynı zamanda dış dünyanın bir kısmını hatırlayabileceği ve etkileşime girebileceği bir depolama bağlamı içeriyordu.

Aynı ihtiyaç OOP dillerinde de mevcuttur, ancak bir işlevin adresini ilettiğinizde, işlevin bir yöntem olduğu nesnenin adresini de iletmeniz gerekir. Bu geçmeniz gereken iki şey. Delege sadece budur ve eski güzel desenin hala kullanılmasına izin verir.


3

DRY ilkesini izleyen basit kod oluşturmada delegelerin ne kadar yararlı olabileceğini gösteren basit bir örnek. Ayrıca kodu gereken yere çok yakın tutmanıza da olanak tanır.

Action<Button, Action<Button>> prepareButton = 
    (btn, nxt) => { 
        btn.Height = 32;
        btn.Width= 64;
        nxt(btn);
    };

prepareButton(myBtn1, btn => btn.Text = "A");
prepareButton(myBtn2, btn => btn.Text = "B");
prepareButton(myBtn3, btn => btn.Text = "C");

İşte delegelerin sağladığı avantajın gerçek dünya örneği.

protected override void PageInitialize()
{
    const string selectCodeFormat = "javascript:selectCode('{0}', '{1}');";
    const string onClick = "return toggleElement(this);";

    Func<HtmlGenericControl> getElement = null;
    Action<HtmlGenericControl> setElement = null, addChild = null;
    HtmlGenericControl level1Element = null, level2Element = null, level3Element = null, level4Element = null;
    string className = null, code = null, description = null;           

    using (var records = Core.Database.ExecuteRecords("code.SocCodeTree"))
    {
        while (records.Read())
        {
            code = records.GetString("Code");
            description = records.GetString("Description"); 

            if (records.GetString("Level4") != "")
            {
                className = "Level4";
                setElement = e => level4Element = e;
                getElement = () => level4Element;
                addChild = e => level3Element.Controls.Add(e);
            }
            else if (records.GetString("Level3") != "")
            {
                className = "Level3";
                setElement = e => level3Element = e;
                getElement = () => level3Element;
                addChild = e => level2Element.Controls.Add(e);
            }
            else if (records.GetString("Level2") != "")
            {
                className = "Level2";
                setElement = e => level2Element = e;
                getElement = () => level2Element;
                addChild = e => level1Element.Controls.Add(e);
            }
            else
            {
                className = "Level1";
                setElement = e => level1Element = e;
                getElement = () => level1Element;
                addChild = e => Root.Controls.Add(e);
            }

            var child = new HtmlGenericControl("li");
            child.Attributes["class"] = className;
            var span = new HtmlGenericControl("span") { 
                InnerText = code + " - " + description + " - " 
            };
            span.Attributes["onclick"] = onClick;
            child.Controls.Add(span);
            var a = new HtmlAnchor() { 
                InnerText = "Select", 
                HRef = string.Format(selectCodeFormat, code, description) 
            };
            child.Controls.Add(a);
            setElement(new HtmlGenericControl("ul"));
            child.Controls.Add(getElement());
            addChild(child);    
        }
    }
}

2

Delegelerle ilk karşılaşmam, web sitemden bir dosya indirerek bir program güncellemesi (Windows C # 3.5 formları) kontrol ediyordu, ancak güncellemenin tüm programı kilitlemesini kontrol etmekten kaçınmak için senkronize olmayan bir şekilde bir temsilci ve bir iş parçacığı kullandım.


1

Delegeleri etkili bir şekilde kullanan Strateji modelinin ilginç uygulamalarını gördüm. (yani strateji bir temsilcidir)

Baktığım yol, yolu bulmak için algoritmanın çalışma zamanında (yeniden) atanabilecek bir temsilci olduğu yol bulma içindi, böylece farklı algoritmalar kullanılabilirdi (BFS vs A * vb.)


1

Klasik GoF kalıplarının çoğu delegelerle uygulanabilir: Örneğin, Komut kalıbı, Ziyaretçi kalıbı, Strateji kalıbı, Fabrika kalıbı ve Gözlemci kalıbı genellikle basit bir delege ile uygulanabilir. Bazen, bir sınıf daha iyidir (örneğin, bir komutun bir ad veya bir strateji nesnesinin serileştirilmesi gerektiğinde), ancak çoğu durumda Action<...>veya yöntemini kullanmak Func<...>, özel bir tek yöntem arabirimi oluşturmaktan çok daha zariftir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.