Why does ConcurrentDictionary.TryRemove require a second out argument?

后端 未结 4 1709
执笔经年
执笔经年 2020-12-15 15:03

I only want to remove a value.. I don\'t need to use the variable afterwards. Why not include an overload where this second parameter was not required?

Do I really h

相关标签:
4条回答
  • 2020-12-15 15:29

    C#7 added discard syntactic sugar

    So now you can write:

    dictionary.TryRemove(entry.Key, out _); 
    

    Reference

    We allow "discards" as out parameters as well, in the form of a _, to let you ignore out parameters you don’t care about:

    p.GetCoordinates(out var x, out _); // I only care about x

    0 讨论(0)
  • 2020-12-15 15:35

    I believe the 2nd argument is required is because you may need to do something with the item that you're removing from ConcurrentDictionary.

    For example, imagine you have a ConcurrentDictionary<int, MyDisposable> where MyDisposable implements IDisposable. ConcurrentDictionary.TryRemove(...) doesn't call .Dispose(); on the item being removed from the dictionary.

    In the code below, the .Dispose(); call succeeds because the MyDisposable hasn't been disposed, yet.

    void Main()
    {
        var dict = new ConcurrentDictionary<int, MyDisposable>();
    
        dict.TryAdd(1, new MyDisposable());
    
        dict.TryRemove(1, out var d);
    
        d.Dispose();
    }
    
    public class MyDisposable : IDisposable {
    
        #region IDisposable Support
        private bool disposedValue = false; // To detect redundant calls
    
        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: dispose managed state (managed objects).
                }
    
                // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
                // TODO: set large fields to null.
    
                disposedValue = true;
            }
        }
    
        // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
        // ~MyDisposable()
        // {
        //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        //   Dispose(false);
        // }
    
        // This code added to correctly implement the disposable pattern.
        public void Dispose()
        {
            // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
            Dispose(true);
            // TODO: uncomment the following line if the finalizer is overridden above.
            // GC.SuppressFinalize(this);
        }
        #endregion
    
    }
    
    0 讨论(0)
  • 2020-12-15 15:36

    If you're not interested in the value that was removed, simply call IDictionary.Remove(key). It's shadowed, so you have to invoke it explicitly.

    Example:

    var dict = new ConcurrentDictionary<string, string>();
    dict.AddOrUpdate("mykey", (val) => "test", (val1, val2) => "test");
    ((IDictionary)dict).Remove("mykey");
    

    The TryRemove(key, out value) method is there to give you feedback whether the operation made any change. Use the one that best suits your needs.

    0 讨论(0)
  • 2020-12-15 15:40

    You can create exactly the method you want:

    public static class ConcurrentDictionaryEx {
      public static bool TryRemove<TKey, TValue>(
        this ConcurrentDictionary<TKey, TValue> self, TKey key) {
        TValue ignored;
        return self.TryRemove(key, out ignored);
      }
    }
    

    UPDATE: Or, as Dialecticus mentioned in the comments, just use Remove. But note that, since it's an explicit interface implementation, you'll need a reference to an IDictionary<TKey, TValue>, which leads you back to creating an extension method if you want to avoid casting a ConcurrentDictionary<TKey, TValue> reference:

    public static class ConcurrentDictionaryEx {
      public static bool Remove<TKey, TValue>(
        this ConcurrentDictionary<TKey, TValue> self, TKey key) {
          return ((IDictionary<TKey, TValue>)self).Remove(key);
      }
    }
    
    0 讨论(0)
提交回复
热议问题