Проблема была вызвана тем, что Fedora, по-видимому, делала обновление glibc без моего взаимодействия.
Исследование, проведенное с помощью GDB, показало, что функциональность libc вызывается неправильно.
Итак, я перезагрузился. Проблема кажется решенной.
Для выполнения задачи кэширования можно следовать за другими предложениями и создать Словарь <Предикат <Нечто>, Список <Нечто>> (статичный для глобального, или членское поле иначе), это кэширует результаты. Прежде на самом деле выполнить Предикат <Нечто>, необходимо было бы проверить, существует ли результат уже в словаре.
Общее название для этого детерминированного функционального кэширования называют Memoization - и его потрясающее :)
С тех пор, как C# 3.0 добавил лямбду и добыча делегатов Func/Action, добавив, что Memoization к C# довольно легок.
У Wes Dyer есть большое сообщение, которое приносит понятие к C# с некоторыми яркими примерами.
Если Вы хотите, чтобы я показал Вам, как сделать это, сообщите мне... иначе, сообщение Wes должно соответствовать.
В ответе на Ваш запрос о хэш-кодах делегата. Если два делегата являются тем же, d1. GetHashCode () должен равняться d2. GetHashCode (), но я не 100% об этом. Можно проверить это быстро путем предоставления Memoization движения и добавления WriteLine в метод FindAll. Если это заканчивает тем, что не было верно, другая опция состоит в том, чтобы использовать Linq. Выражение <Предикат <Нечто>> в качестве параметра. Если выражения не являются закрытиями, то выражения, которые делают то же самое, должны быть равными.
Сообщите мне, как это идет, мне интересно знать ответ о делегате. Равняется.
Если Вы не уверены, что реализация Делегатом GetHashCode детерминирована и не приводит ни к каким коллизиям, я не доверял бы ему.
Вот две идеи. Во-первых, сохраните результаты делегатов в рамках словаря Предиката/Списка, с помощью предиката в качестве ключа, и затем сохраните весь словарь результатов под единственным ключом в кэше. Плохая вещь состоит в том, что Вы теряете все свои кэшируемые результаты, если объект кэша потерян.
Альтернатива должна была бы создать дополнительный метод для Предиката, GetKey (), который использует словарь объекта/строки, чтобы сохранить и получить все ключи для всех Предикатов. Вы индексируете в словарь с делегатом и возвращаете его ключ, создавая тот, если Вы не находите его. Таким образом, Вас уверяют, что Вы получаете корректный ключ на делегата и нет никаких коллизий. Наивный был бы именем типа + Гуид.
Равенство делегата смотрит на каждый вызов в списке вызова, тестирующем на равенство метода, который будет вызван, и цель метода.
Метод является простой частью ключа кэша, но цель метода (экземпляр для обращения к нему - принятие метода экземпляра) могло быть невозможно кэшировать сериализуемым способом. В частности, для анонимных функций, которые получают состояние, это будет экземпляр вложенного класса, созданного для получения того состояния.
Если это - все в памяти, просто сохранив делегата самой, как ключ хеша будет хорошо - хотя это может означать, что некоторые объекты, какие клиенты ожидали бы быть собранными "мусор", бродят вокруг. Если необходимо сериализировать это к базе данных, это становится более волосатым.
Вы могли заставить свой метод принять ключ кэша (например, строка) также? (Это принимает в кэше памяти, является несоответствующим.)
Тот же экземпляр объекта будет всегда возвращать тот же хэш-код (требование GetHashCode () в .NET). Если Ваши предикаты в статическом списке, и Вы не переопределяете их каждый раз, когда я не вижу проблемы в использовании их как ключи.
При сохранении кэшируемых результатов в Словаре <Предикатом <Нечто>, Список <Нечто>> является неловким для меня, потому что я хочу, чтобы кэш 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 с, по-видимому, тем же анонимным методом не совместно использует кэшируемые результаты, но это должно быть довольно редко.