Ну, во-первых, эта строка:
return Values.Single(g => g.date == date).value;
делает так, чтобы последующие строки никогда не вызывались.Я предполагаю, что вы немного перефразировали свой код здесь?
Если вы хотите синхронизировать записи в ваш список Values
, самый простой способ будет lock
для общего объекта повсюду вкод, который вы изменяете в списке:
int value = GetValueFor(date);
lock (dedicatedLockObject) {
Values.Add(new PrecalculateValue{date = date, value = value});
}
return value;
Но здесь стоит отметить еще кое-что: поскольку похоже, что вы хотите иметь один PrecalculateValue
на DateTime
, более подходящая структура данных, вероятно, будетбыть Dictionary<DateTime, PrecalculateValue>
- он обеспечит молниеносный поиск O (1) на основе вашей клавиши DateTime
, по сравнению с List<PrecalculateValue>
, который должен был бы повторяться, чтобы найти то, что вы ищете.
С этим изменением ваш код может выглядеть примерно так:
public class Billing
{
private Dictionary<DateTime, PrecalculateValue> Values =
new Dictionary<DateTime, PrecalculateValue>();
private readonly commonLockObject = new object();
public int GetValue(DateTime date)
{
PrecalculateValue cachedCalculation;
// Note: for true thread safety, you need to lock reads as well as
// writes, to ensure that a write happening concurrently with a read
// does not corrupt state.
lock (commonLockObject) {
if (Values.TryGetValue(date, out cachedCalculation))
return cachedCalculation.value;
}
int value = GetValueFor(date);
// Here we need to check if the key exists again, just in case another
// thread added an item since we last checked.
// Also be sure to lock ANYWHERE ELSE you're manipulating
// or reading from the collection.
lock (commonLockObject) {
if (!Values.ContainsKey(date))
Values[date] = new PrecalculateValue{date = date, value = value};
}
return value;
}
private object GetValueFor(DateTime date)
{
//some logic here
}
}
И последний совет: если не важно, чтобы в вашей коллекции существовало не более одного значения.метод Single
является излишним.Если вы предпочитаете просто получить первое значение и не обращать внимания на потенциальные дубликаты, First
является одновременно более безопасным (как, с меньшей вероятностью исключения) и более быстрым (потому что он не должен повторяться по всей коллекции).