09.09.2018 Как такое сделать без блокировок?
 
Привет всем!

Пусть имеется множество строковых ключей. На нем вводится отношение эквивалетности, порожденное функцией ConstraintExpression.Canonize.
Этих ключей извне приходит большое количество, и по каждому нужно взять объект чтобы выполнить на нем относительно тяжеловесную обработку.
Для ключей в пределах класса эквивалентности вся обработка одинаковая. Однако инициализация перед ее началом занимает много ресурсов.
Инициализация частично отложенная, так что создать новый объект хоть и дороже, чем не создавать его, но гораздо дешевле, чем использовать
новый объект для вызова DoHardWork вместо ранее созданного эквивалентного.

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

public class Factory 
{
  public Constraint Create( string expression )
  {
    lock ( lock_ )
    {
      Constraint candidate;
      if ( map_.TryGetValue( expression, out candidate ) )
      {
        return candidate;
      }

      candidate = new Constraint( expression );
      var canonic = candidate.Canonic;
      
      Constraint result;
      if ( !map_.TryGetValue( canonic, out result ) )
      {
        result = candidate;
        map_[canonic] = result;
      }

      map_[expression] = result;
      return result;
    }
  }

  private readonly IDictionary<string, Constraint> map_ = new Dictionary<string, Constraint>( StringComparer.InvariantCultureIgnoreCase );
  private readonly object lock_ = new object();
}
public class Constraint
{
  public Constraint( string expression )
  {    
    Expression = expression;
    Canonic = Canonize( expression );      
  }
  public string Expression { get; private set; }
  public string Canonic { get; private set; }
  
  public string DoHardWork() {}
  
  private string Canonize( string key ) { return key.ToLower(); } // Только для примера
}

А вопрос в том, можно ли переписать фабрику без блокировок?

Спасибо.

 
 
 
 
10.12  .NET Reactor
15.11  n
15.11  C# ClickOnce