Frage

Ich habe eine C# - Methode, die ein Prädikat akzeptiert<Foo> und gibt eine Liste passender Artikel...

public static List<Foo> FindAll( Predicate<Foo> filter )
{
    ...
}

Der filter wird oft ein gemeinsamer...

public static class FooPredicates
{
    public static readonly Predicate<Foo> IsEligible = ( foo => ...)
    ...
}

...kann aber sein, einen anonymen Delegaten.

Jetzt möchte ich gerne diese Methode, cache-Ihre Ergebnisse in der ASP.NET cache, so wiederholte Aufrufe mit den gleichen delegieren, der gerade wieder das zwischengespeicherte Ergebnis.Für diese brauche ich, um erstellen Sie einen cache-Schlüssel aus der Stellvertretung.Delegieren.GetHashCode() vernünftige Ergebnisse für diesen Zweck?Gibt es irgendein anderes Mitglied Delegieren, die ich anschauen sollte?Würden Sie einen anderen Weg vollständig?

War es hilfreich?

Lösung

Ihre Caching-Aufgabe auszuführen, können Sie die anderen Vorschläge folgen und ein Dictionary , List > (statisch für globale oder Mitgliedsfeld auf andere Weise) erstellen, die die Ergebnisse zwischenspeichert. Bevor tatsächlich das Prädikat Ausführen, würden Sie überprüfen müssen, wenn das Ergebnis bereits im Wörterbuch vorhanden ist.

Der allgemeine Name für diese deterministische Funktion Caching memoization genannt - und seine genial:)

Seit C # 3.0 LAMBDA gegeben, und die Beute von Func / Action-Delegierten, das Hinzufügen memoization zu C # ist ganz einfach.

Wes Dyer hat einen großen Beitrag rel="nofollow , dass das Konzept C # mit einigen großen Beispielen bringt.

Wenn Sie wollen, dass ich Ihnen zeigen, wie dies zu tun, lassen Sie mich wissen ... sonst, Wes' Post ausreichend sein sollte.

In der Antwort auf Ihre Frage über Delegaten Hash-Codes. Wenn zwei Teilnehmer die gleiche, d1.GetHashCode () sind, sollten gleich d2.GetHashCode (), aber ich bin nicht 100% darüber. Sie können dies schnell überprüfen, indem memoization einen gehen zu geben, und eine Console.WriteLine in Ihre FindAll Methode hinzufügen. Wenn dies endet nicht wahr zu sein, ist eine weitere Option Linq.Expression > als Parameter zu verwenden. Wenn die Ausdrücke sind nicht Schließungen, dann Ausdrücke, die das gleiche tun sollte gleich sein.

Lassen Sie mich wissen, wie das geht, ich bin daran interessiert, die Antwort über delegate.Equals zu kennen.

Andere Tipps

Delegieren der Geschlechter sieht bei jedem Aufruf in der Aufruf Liste, die Prüfung auf Gleichheit der Methode aufgerufen werden, und Ziel der Methode.

Die Methode ist eine einfache Stück von der cache-Schlüssel, aber das Ziel der Methode (die Instanz aufrufen, es auf - vorausgesetzt, eine Instanz-Methode) könnte unmöglich sein, den cache in eine serialisierbare Weg.Insbesondere für anonyme Funktionen, die erfassen, so wird der Zustand einer Instanz der geschachtelten Klasse erstellt, um zu erfassen, dass Staat.

Wenn dies alles im Gedächtnis, nur halten die Delegierten sich als hash-Schlüssel wird in Ordnung sein - obwohl es kann bedeuten, dass einige Objekte, die Kunden würden erwarten, dass Müll gesammelt hängen herum.Wenn Sie brauchen, um dies serialisieren zu einer Datenbank, es wird hairier.

Könnten Sie die Methode zum annehmen eines cache-Schlüssel (z.B.ein string) as well?(Das setzt Voraus, dass ein cache-Speicher ist unzureichend.)

Halten Sie die zwischengespeicherten Ergebnisse in einem Dictionary , List > ist für mich peinlich, weil ich die ASP.NET-Cache wollen Ablauf behandeln für mich, anstatt alle Ergebnisse Cachen für immer, aber es ist sonst ein gutes Lösung. Ich glaube, ich mit Wills Dictionary , string> am Ende gehen würde eine Zeichenfolge cachen, die ich in dem ASP.NET-Cache-Schlüssel verwenden kann.

Einige ersten Tests deuten darauf hin, dass Delegierten Gleichheit tut das „Richtige“, wie andere gesagt haben, aber Delegate.GetHashCode ist pathologisch nicht hilfreich. Reflector zeigt

public override int GetHashCode()
{
    return base.GetType().GetHashCode();
}

So eine Predicate liefert das gleiche Ergebnis.

Meine noch offene Frage war, wie die Gleichstellung von anonym Delegierten funktioniert. Was bedeutet „gleiche Methode auf das gleiche Ziel namens“ bedeutet dann? Es scheint, dass, solange die Delegierten an der gleichen Stelle definiert wurden, Referenzen gleich sind. Die Delegierten mit dem gleichen Körper an verschiedenen Stellen definiert sind es nicht.

static Predicate<int> Test()
{
    Predicate<int> test = delegate(int i) { return false; };
    return test;
}

static void Main()
{
    Predicate<int> test1 = Test();
    Predicate<int> test2 = Test();
    Console.WriteLine(test1.Equals( test2 )); // True

    test1 = delegate(int i) { return false; };
    test2 = delegate(int i) { return false; };
    Console.WriteLine(test1.Equals( test2 )); // False
}

Dies sollte für meine Bedürfnisse in Ordnung sein. Anrufe mit den vordefinierten Prädikate werden im Cache gespeichert werden. Mehrere Anrufe auf eine Methode, die FindAll mit einer anonymen Methode aufruft sollte zwischengespeichert Ergebnisse. Zwei Methoden FindAll mit scheinbar gleicher anonymer Aufruf der Methode werden nicht im Cache gespeichert Ergebnisse teilen, aber das sollte ziemlich selten sein.

Wenn Sie nicht sicher sind, dass Delegate Implementierung von GetHashCode deterministisch ist und führt nicht zu irgendwelchen Kollisionen würde ich ihm nicht vertrauen.

Hier zwei Ideen. Zuerst speichern die Ergebnisse der Delegierten innerhalb eines Prädikats / List-Wörterbuch, das Prädikat als Schlüssel, und speichern Sie dann das gesamte Wörterbuch der Ergebnisse unter einem einzigen Schlüssel im Cache. Schlimme ist, dass Sie alle Ihre Ergebnisse aus dem Cache verlieren, wenn das Cache-Element verloren.

Eine Alternative wäre eine Erweiterungsmethode für Prädikats, GetKey () zu erstellen, die ein Objekt / string Wörterbuch verwendet alle Schlüssel für alle Prädikate zu speichern und abzurufen. Sie Index in das Wörterbuch mit den Delegierten und dessen Schlüssel zurückgeben, wodurch ein, wenn Sie es nicht finden. Auf diese Weise Sie sicher sein, dass Sie den richtigen Schlüssel pro Teilnehmer bekommen und es gibt keine Kollisionen. Ein naiive würde man Typname + Guid sein.

Die gleiche Instanz eines Objekts wird immer geben den gleichen Hash-Code (Anforderung von GetHashCode () in .NET). Wenn Ihre Prädikate innerhalb einer statischen Liste sind und Sie sie nicht jedes Mal neu festlegen, kann ich nicht ein Problem im Umgang mit ihnen als Schlüssel sehen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top