2010-06-24 10 views
11

Kann mir jemand die Vorteile der Verwendung eines Delegaten im Gegensatz zum Aufruf der Funktion selbst, wie unten gezeigt (oder mit anderen Worten, warum Option A über Option B wählen) sagen? Ich habe letzte Nacht jemandes Linq-Code angeschaut und sie hatten etwas Ähnliches wie Option A, aber es wurde verwendet, um eine kompilierte Linq-Abfrage zurückzugeben.Func Delegat vs Funktion

Ich realisiere, dass der ehemalige kann jetzt zu anderen Funktionen weitergegeben werden .. nur nicht sicher, seine Praktikabilität. BTW, merke ich, dass das nicht kompiliert werden würde .. unkommentiert eine der Funktionen vor dem Posten. TYIA

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine(SayTwoWords("Hello", "World")); 
     Console.ReadKey(); 
    } 

    // Option A 
    private static Func<string, string, string> 
     SayTwoWords = (a, b) => String.Format("{0} {1}", a, b); 

    // Option B 
    private static string SayTwoWords(string a, string b) 
    { 
     return String.Format("{0} {1}", a, b); 
    }   
} 

************ EDIT ************

nicht sicher, ob es meine Frage besser erklärt, aber hier ist ein Beispiel von der Art des Codes, den ich darüber nachgedacht ursprünglich bekam:

public static class clsCompiledQuery 
{ 
    public static Func<DataContext, string, IQueryable<clsCustomerEntity>> 
     getCustomers = CompiledQuery.Compile((DataContext db, string strCustCode) 
      => from objCustomer in db.GetTable<clsCustomerEntity>() 
      where objCustomer.CustomerCode == strCustCode 
      select objCustomer); 
} 

gibt es einen Vorteil, um eine Funktion auf diese Weise zu schreiben?

+0

möglich Duplikat von [Ich bekomme immer noch keine Delegierten] (http://stackoverflow.com/questions/399222/i-still-dont-get-delegates) –

Antwort

13

Es gibt keinen Vorteil in dem Code, den Sie gepostet haben. In Ihrem Code sorgt die Verwendung des Delegaten für zusätzliche Komplexität und zusätzliche Laufzeitkosten. Sie können also die Methode direkt aufrufen.

Delegierten haben jedoch viele Anwendungen. "Umgehen" zu anderen Methoden ist die primäre Verwendung, obwohl das Speichern einer Funktion und deren spätere Verwendung ebenfalls sehr nützlich ist.

LINQ baut vollständig auf diesem Konzept auf. Wenn Sie das tun:

var results = myCollection.Where(item => item == "Foo"); 

Sie vorbei einen Delegierten (als Lambda definiert: item => item == "Foo") an die Where Funktion in den LINQ-Bibliotheken. Dies ist es, was es richtig funktioniert.

3

Es ist nur nützlich, wenn Sie den Delegierten übergeben müssen. Wenn Sie die Funktion zum Zeitpunkt der Kompilierung auflösen können, ist dies weniger nützlich.

+0

Sie können jede vorhandene Funktion in einer Zeile, I delegieren glaube nicht, dass es einen Vorteil gibt, es sei denn, du machst es mehr als 10.000 mal (weniger Objekte erstellt). – Aren

1

Sie können Delegaten als "Funktionszeiger" verwenden, damit Sie anderen Funktionen Funktionen oder "Aktionen" zuweisen können.

was auch mit den Delegierten wäre interessant ist die Möglichkeit, „Vorkompilieren“, wie Sie „bauen“ eine neue Funktion und dann diese Funktion, um Ihre Anwendung zurück

2

Bei der statischen Methode, die Sie in allen passieren müssen die Variablen benötigt.
Mit dem Delegaten können Sie Ihre Implementierung inline und Zugriff auf die Variablen im Bereich haben.

4

Eine sehr nützliche Funktion von Delegaten ist, dass Sie sie senden können, wo immer Sie wollen. Es ist so, als ob Sie Ihre Funktion überall dort haben, wo Sie sie brauchen. Ein großer Nutzen hierfür ist die Ereignisbehandlung. Angenommen, Sie haben eine Schaltfläche, und wenn ein Benutzer auf diese Schaltfläche klickt, möchten Sie eine beliebige Anzahl von Funktionen aufrufen. Wenn Sie darüber nachdenken, ein paar Möglichkeiten, es könnte Sie dies tun:

Sie könnten: Anruf eine Funktion, die jede andere Funktion ruft Sie angerufen werden soll. Das bedeutet, dass Sie für jede neue Funktion, die Sie aufrufen möchten, diese Funktion fest codieren müssen. Sehr nervig.

OR Sie könnten eine öffentliche Liste mit den Namen der einzelnen Funktionen Sie anrufen wollen, müssen (Delegierte), und jeder kann diese Funktionen jederzeit ohne dass der Besitzer des Click-Ereignis hinzuzufügen oder zu entfernen, die wissen, oder tun Sie sogar irgendeine Arbeit bezüglich irgendwelcher von ihnen. Wenn das Click-Ereignis eintritt, wird jedes Ereignis in der Liste aufgerufen und die gleichen Parameter gesendet, und Sie sind fertig.

1
// Option A 
private static Func<string, string, string> 
    SayTwoWords = (a, b) => String.Format("{0} {1}", a, b); 

// Option B 
private static string SayTwoWords(string a, string b) 
{ 
    return String.Format("{0} {1}", a, b); 
} 

Im obigen Fall ist Option B, was mit Ich würde, wenn ich nicht alle Funktionen in SayTwoWords müssen geändert werden. Bei Option A kann SayTwoWords eine andere Funktion zugewiesen werden. Catch detailliertere Unterschiede in this answer:

Es gibt eine Situation, in der Option A sinnvoll ist. Betrachten Sie einen Fall, in dem Sie einen Ausdruck für einen Delegaten kompilieren müssen. Da die Ausdruckerstellung schwer ist, möchten Sie dies nur einmal tun. Ein Muster wie das hilft:

public static class Cache<T> 
{ 
    public static readonly Func<T> Get = GetImpl(); 

    static Func<T> GetImpl() 
    { 
     //build expression and return compiled delegate 
    } 
} 

statt

public static class Cache<T> 
{ 
    public static T Get() 
    { 
     //build expression, compile delegate and invoke the delegate 
    } 
} 

Im ersten Fall, wenn Sie Get nennen, GetImpl nur einmal ausgeführt wird, wo wie im zweiten Fall (teuer) Get werden jedes Mal aufgerufen.