Кэширование результатов делегата

Проблема была вызвана тем, что Fedora, по-видимому, делала обновление glibc без моего взаимодействия.

Исследование, проведенное с помощью GDB, показало, что функциональность libc вызывается неправильно.

Итак, я перезагрузился. Проблема кажется решенной.

7
задан Chris McCall 30 July 2009 в 15:58
поделиться

5 ответов

Для выполнения задачи кэширования можно следовать за другими предложениями и создать Словарь <Предикат <Нечто>, Список <Нечто>> (статичный для глобального, или членское поле иначе), это кэширует результаты. Прежде на самом деле выполнить Предикат <Нечто>, необходимо было бы проверить, существует ли результат уже в словаре.

Общее название для этого детерминированного функционального кэширования называют Memoization - и его потрясающее :)

С тех пор, как C# 3.0 добавил лямбду и добыча делегатов Func/Action, добавив, что Memoization к C# довольно легок.

У Wes Dyer есть большое сообщение, которое приносит понятие к C# с некоторыми яркими примерами.

Если Вы хотите, чтобы я показал Вам, как сделать это, сообщите мне... иначе, сообщение Wes должно соответствовать.

В ответе на Ваш запрос о хэш-кодах делегата. Если два делегата являются тем же, d1. GetHashCode () должен равняться d2. GetHashCode (), но я не 100% об этом. Можно проверить это быстро путем предоставления Memoization движения и добавления WriteLine в метод FindAll. Если это заканчивает тем, что не было верно, другая опция состоит в том, чтобы использовать Linq. Выражение <Предикат <Нечто>> в качестве параметра. Если выражения не являются закрытиями, то выражения, которые делают то же самое, должны быть равными.

Сообщите мне, как это идет, мне интересно знать ответ о делегате. Равняется.

4
ответ дан 7 December 2019 в 03:22
поделиться

Если Вы не уверены, что реализация Делегатом GetHashCode детерминирована и не приводит ни к каким коллизиям, я не доверял бы ему.

Вот две идеи. Во-первых, сохраните результаты делегатов в рамках словаря Предиката/Списка, с помощью предиката в качестве ключа, и затем сохраните весь словарь результатов под единственным ключом в кэше. Плохая вещь состоит в том, что Вы теряете все свои кэшируемые результаты, если объект кэша потерян.

Альтернатива должна была бы создать дополнительный метод для Предиката, GetKey (), который использует словарь объекта/строки, чтобы сохранить и получить все ключи для всех Предикатов. Вы индексируете в словарь с делегатом и возвращаете его ключ, создавая тот, если Вы не находите его. Таким образом, Вас уверяют, что Вы получаете корректный ключ на делегата и нет никаких коллизий. Наивный был бы именем типа + Гуид.

1
ответ дан 7 December 2019 в 03:22
поделиться

Равенство делегата смотрит на каждый вызов в списке вызова, тестирующем на равенство метода, который будет вызван, и цель метода.

Метод является простой частью ключа кэша, но цель метода (экземпляр для обращения к нему - принятие метода экземпляра) могло быть невозможно кэшировать сериализуемым способом. В частности, для анонимных функций, которые получают состояние, это будет экземпляр вложенного класса, созданного для получения того состояния.

Если это - все в памяти, просто сохранив делегата самой, как ключ хеша будет хорошо - хотя это может означать, что некоторые объекты, какие клиенты ожидали бы быть собранными "мусор", бродят вокруг. Если необходимо сериализировать это к базе данных, это становится более волосатым.

Вы могли заставить свой метод принять ключ кэша (например, строка) также? (Это принимает в кэше памяти, является несоответствующим.)

2
ответ дан 7 December 2019 в 03:22
поделиться

Тот же экземпляр объекта будет всегда возвращать тот же хэш-код (требование GetHashCode () в .NET). Если Ваши предикаты в статическом списке, и Вы не переопределяете их каждый раз, когда я не вижу проблемы в использовании их как ключи.

0
ответ дан 7 December 2019 в 03:22
поделиться

При сохранении кэшируемых результатов в Словаре <Предикатом <Нечто>, Список <Нечто>> является неловким для меня, потому что я хочу, чтобы кэш ASP.NET обработал истечение для меня вместо того, чтобы кэшировать все результаты навсегда, но это - иначе хорошее решение. Я думаю, что закончу тем, что шел со Словарем Желания <Предикат <Нечто>, строка> для кэширования строки, которую я могу использовать в ключе кэша ASP.NET.

Некоторые начальные тесты предполагают, что равенство делегата делает "правильную вещь", как другие сказали, но Делегат. GetHashCode патологически бесполезен. Отражатель показывает

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

Таким образом, любой Предикат <Нечто> возвращает тот же результат.

Моя остающаяся проблема была то, как равенство работает на анонимных делегатов. То, что делает "тот же метод, обратилось к той же цели", средней затем? Кажется, что, пока делегат был определен в том же месте, ссылки равны. Делегаты с тем же телом, определенным в различных местах, не.

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
}

Это должно быть хорошо для моих потребностей. Вызовы с предопределенными предикатами будут кэшироваться. Множественные вызовы одного метода, который называет FindAll с анонимным методом, должны получить кэшируемые результаты. Два вызова методов FindAll с, по-видимому, тем же анонимным методом не совместно использует кэшируемые результаты, но это должно быть довольно редко.

2
ответ дан 7 December 2019 в 03:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: