title: Is this implementation thread safe?
body: <p>I have following classes:</p>
  
  <pre><code>public interface IApplicationEncryptionService
  {
      string Encrypt(string message);
  
      string Decrypt(string cipher);
  }
  
  public class ApplicationEncryptionService : IApplicationEncryptionService
  {
      private IApplicationEncryptionCacheHelper m_cacheHelper;
  
      public ApplicationEncryptionService(IApplicationEncryptionCacheHelper cacheHelper = null)
      {
          if (cacheHelper == null)
              m_cacheHelper = new ApplicationEncryptionCacheHelper();
  
      }
  
      public string Encrypt(string input)
      {
          //Encrypt
      }
  
      public string Decrypt(string input)
      {
          //Decrypt
      }
  }
  
  public interface IApplicationEncryptionCacheHelper
  {
      void Add&lt;T&gt;(string key, T objectToCache) where T : class, new();
      T Get&lt;T&gt;(string key) where T : class, new();
      void Remove(string key);
  }
  
  
  class ApplicationEncryptionCacheHelper : IApplicationEncryptionCacheHelper
  {
      private const string CACHE_NAME = "EncryptionCache";
  
      private static CacheProvider m_CacheProvider = new CacheProvider();     
      private CacheNameConfiguration m_defaultCacheConfiguration;
  
      public ApplicationEncryptionCacheHelper()
      {
          m_defaultCacheConfiguration = new CacheConfiguration
          {
              IsRemovable = true,
              ExpirationType = CacheNameConfiguration.ExpirationOption.Sliding,
              ExpirationInterval = new TimeSpan(0, 60, 0)
          };
      }
  
      public void Add&lt;T&gt;(string key, T objectToCache) where T : class, new()
      {
          m_CacheProvider.Add(CACHE_NAME, key, objectToCache, m_defaultCacheConfiguration);
      }
  
      public T Get&lt;T&gt;(string key) where T : class, new()
      {
          var itemFromCache = m_CacheProvider.Get(CACHE_NAME, key);
          return (T)itemFromCache;
      }
  
      public void Remove(string key)
      {
          m_CacheProvider.Remove(CACHE_NAME, key);
      }
  }
  
  class CacheProvider
  {
      private ConcurrentDictionary&lt;string, MemoryCache&gt; m_localCacheLookup = new ConcurrentDictionary&lt;string, MemoryCache&gt;();
  
      public override void Add(string cacheName, string key, object itemToCache, CacheNameConfiguration cacheNameConfiguration)
      {
          MemoryCache cacheManager = GetCacheManager(cacheName);
  
          CacheItemPriority cacheItemPriority = cacheNameConfiguration.IsRemovable ? CacheItemPriority.Default : CacheItemPriority.NotRemovable;
          CacheItemPolicy policy;
          if (cacheNameConfiguration.ExpirationType == CacheNameConfiguration.ExpirationOption.Sliding)
          {
              policy = new CacheItemPolicy { SlidingExpiration = cacheNameConfiguration.ExpirationInterval, Priority = cacheItemPriority };
          }
          else
          {
              policy = new CacheItemPolicy { AbsoluteExpiration = new DateTimeOffset(DateTime.UtcNow, cacheNameConfiguration.ExpirationInterval), Priority = cacheItemPriority };
          }
  
          cacheManager.Add(key, itemToCache, policy);
      }
  
      public override object Get(string cacheName, string key)
      {
          MemoryCache cacheManager = GetCacheManager(cacheName);
  
          return cacheManager.Get(key);
      }
  
      public override void Remove(string cacheName, string key)
      {
          MemoryCache cacheManager = GetCacheManager(cacheName);
  
          cacheManager.Remove(key);
      }
  
      #endregion
  
      #region Private Methods
  
      private MemoryCache GetCacheManager(string cacheName)
      {
          return m_localCacheLookup.GetOrAdd(cacheName, (cacheKey) =&gt;
          {
              NameValueCollection config = new NameValueCollection();
              config.Add("pollingInterval", "00:30:00");
              return new MemoryCache(cacheName, config);
          });
      }
  }
  </code></pre>
  
  <p>ApplicationEncryptionService will be used by different threads and uses  ApplicationEncryptionCacheHelper to Cache frequently used data.</p>
  
  <p>ApplicationEncryptionCacheHelper contains an instance of CacheProvider declared as a private static variable. Is it a threadsafe implementation? </p>