Кэширование целое число - различия никакого значения от нуля


Я хотел бы хранить целочисленное значение в кэше приложения.

В GetOrSet метод должен всегда возвращать int, а не быть нулем. Если нет кэшированное значение, то getDataCallback функция будет предоставлять целое.

Но мне нужно кэш проверить, чтобы возвратить интервал nullable для того, чтобы отличить no value из 0 целочисленное значение.

Я ищу какие-либо ошибки в коде ниже, или возможных улучшений.

Это, наверное, выглядит очень просто, но я нахожу, что работать с типами nullable ИНЦ довольно запутанным.

public int GetOrSet(string cacheKey, Func<int> getDataCallback)
{
    int? data = (int?)HttpContext.Current.Application[cacheKey]; // this should return null if there is no value stored in the cache
    if (! data.HasValue)
    {
        int intData = getDataCallback();
        HttpContext.Current.Application[cacheKey] = intData;
        return intData;
    }
    else
    {
        return data.Value;
    }
}

Обновление

Большое спасибо обоим @Nkosiбыл и @Флатер за помощь.

Я отметил ответ @Флатер как верную, потому что мне пришлось выбрать лишь один. Но я действительно ненавидел того, чтобы сделать это, как оба ответа были одинаково полезны и я использовал обе свои предложения в конце. Я бы посоветовала каждый, кто читает это, чтобы проверить их обоих.



Комментарии
3 ответа

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

public int GetData(string cacheKey, Func<int> getDataCallback)
{
int? cachedData = (int?)HttpContext.Current.Application[cacheKey];

return cachedData.HasValue
? cachedData.Value
: CreateCache(cacheKey, getDataCallback);
}

private int CreateCache(string cacheKey, Func<int> getDataCallback)
{
int intData = getDataCallback();
HttpContext.Current.Application[cacheKey] = intData;
return intData;
}

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


  • Код может быть переработан, чтобы немного сократить его, но это было бы в ущерб читабельности.

  • Я переименовал GetOrSet для GetData для ясности ради. Существует способ, чтобы дать вам информацию, независимо от того, кэшированные или создаваться "на лету". Педантично, вы должны были бы назвать его Get_or_SetAndThenGet для того, чтобы быть точное описание. Я предпочитаю GetDataона прилипает к важные факты и остается сжатым.

  • Nkosiбыл тоже правильно в комментариях, что вы в идеале должны аннотация этот фрагмент от использования HttpContextно это не обязательно для вопроса под рукой.


Обратите внимание, что вы могли бы также прекратить использование int? если вас смущает:

public int GetData(string cacheKey, Func<int> getDataCallback)
{
object cachedData = HttpContext.Current.Application[cacheKey];

return cachedData != null
? (int) cachedData
: CreateCache(cacheKey, getDataCallback);
}

2
ответ дан 5 марта 2018 в 11:03 Источник Поделиться

Предполагая, что код, приведенный выше, не является сама по себе абстракция, тесно связывая свой код HttpContext бы не модульного тестирования как HttpContext.Current это null вне IIS.

Считают, что инкапсуляция кода абстракция.

public interface IApplicationCache {
object this[string cacheKey] { get; set}
}

public class ApplicationCacheImplementation {
public object this[string cacheKey] {
get {
return HttpContext.Current.Application[cacheKey];
}
set {
HttpContext.Current.Application[cacheKey] = value;
}
}
}

реализация которых будет явно вводят в зависимый класс.

Кроме этого у вас логика здравая, но также может извлечь выгоду из некоторых защитных кодирование (нулевые чеки на предоставленные аргументы) и разделение интересов.

public class MyClass {
private readonly IApplicationCache applicationCache;

public MyClass(IApplicationCache applicationCache) {
this.applicationCache = applicationCache;
}

public int GetOrSet(string cacheKey, Func<int> valueFactory) {
if (string.IsNullOrWhiteSpace(cacheKey)) throw new ArgumentException("cacheKey");
if (valueFactory == null) throw new ArgumentException("valueFactory");

return (int)(get(cacheKey) ?? set(cacheKey, valueFactory));
}

private object get(string cacheKey) {
return applicationCache[cacheKey];
}

private int set(string cacheKey, Func<int> valueFactory) {
int value = valueFactory();
applicationCache[cacheKey] = value;
return value;
}
}

Обратите внимание на изменение названий, которые помогают сделать код немного более читаемым.

2
ответ дан 5 марта 2018 в 12:03 Источник Поделиться

Больше кода, чем нужно

int? data = (int?)HttpContext.Current.Application[cacheKey]; 
if (! data.HasValue)
{
data = getDataCallback();
HttpContext.Current.Application[cacheKey] = data;
}
return data.Value;

-1
ответ дан 5 марта 2018 в 08:03 Источник Поделиться