Почему Cache.Add возвращает объект, представляющий кешированный элемент?

Из MSDN о различиях между добавлением или добавлением элемента кэш-памяти ASP.NET:

Примечание. Методы добавления и вставки имеют та же подпись, но есть тонкие различия между ними. Во-первых, вызов метода Add возвращает объект, представляющий кешированный элемент, при вызове вставки не. Во-вторых, их поведение разные, если вы вызываете эти методы и добавьте элемент в кэш, который уже хранится там. Вставка метод заменяет элемент, тогда как Ошибка метода добавления. [акцент мой]

Вторая часть проста. Нет вопроса об этом.

Но с первой частью, почему он хочет вернуть объект, представляющий кешированный элемент? Если я пытаюсь добавить элемент в кеш, у меня уже есть/знаю, что это за элемент?

Я не понимаю. Каковы причины этого?

Ответ 1

Вызов Add() в кеше в конечном итоге вызывает внутренний метод с этой сигнатурой:

internal abstract CacheEntry UpdateCache(CacheKey cacheKey, 
    CacheEntry newEntry, bool replace, CacheItemRemovedReason removedReason, 
    out object valueOld);

Обратите внимание на out object valueOld - это устанавливается для объекта, который в настоящее время находится в кеш-кеше, и возвращается в результате добавления(). Документация вводит в заблуждение, на самом деле это не тот же самый объект, который был возвращен, - какой бы объект ни находился в том же ключевом месте.

Это легко проверить с помощью следующего кода:

 String x = "lorem";
 String y = "ipsum";

 HttpContext.Current.Cache.Add("hi", x, null, DateTime.MaxValue, 
                               Cache.NoSlidingExpiration, 
                               CacheItemPriority.Normal, null);

 var z = HttpContext.Current.Cache.Add("hi", y, null, DateTime.MaxValue,
                              Cache.NoSlidingExpiration, 
                              CacheItemPriority.Normal, null);

 //Result:
 //   z == "lorem"

Ответ 2

Чтобы сделать это еще более ясным, вот консольное приложение, демонстрирующее поведение точное:

static void Main(string[] args)
{
    string key = "key";

    HttpRuntime.Cache.Add(key, "first", null/*no depends*/, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null/*no callback*/);
    var addResult = HttpRuntime.Cache.Add(key, "second", null/*no depends*/, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null/*no callback*/);

    Console.WriteLine("addResult = {0}", addResult);
    Console.WriteLine("Cache[key] = {0}", HttpRuntime.Cache[key]);
}

И вывод консоли:

addResult = first
Cache[key] = first

"Второй" вызов .Add возвращает то, что в настоящее время находится в кэше под нашим ключом, а не обновляет запись!

Ответ 3

Если вызов метода Add удался при добавлении элемента, он возвращает null.

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

Логически он должен возвращать объект, уже находящийся в кеше, поскольку это единственная информация, которая вызывает интерес. У вас уже есть ссылка на объект, который вы пытаетесь поместить в кеш.

Ответ 4

Он возвращает объект только в том случае, если тот же объект уже был сохранен в кеше (под другим ключом, который я думаю), под тем же ключом). В противном случае он возвращает null. Документация вводит в заблуждение:

http://msdn.microsoft.com/en-us/library/system.web.caching.cache.add.aspx

Глядя на него в Reflector, оба метода, похоже, вызывают один и тот же внутренний метод: ADD возвращает старый объект, ранее сохраненный под тем же ключом, и метод INSERT просто игнорирует это значение.