I was looking for a method in ConcurrentDictionary that allows me to remove an entry by key, if and only if the value is equal to one that I specify, something like the equivalent of TryUpdate, but for removals.
The only method that does this seems to be this method:
ICollection<KeyValuePair<K, V>>.Remove(KeyValuePair<K, V> keyValuePair)
It is the explicit implementation of the ICollection interface, in other words, I have to cast my ConcurrentDictionary to an ICollection first so that I can call Remove.
Remove does exactly what I want, and that cast is no big deal either, also the source code shows it calls the private method TryRemovalInternal with bool matchValue = true, so it all looks nice and clean.
What worries me a bit however is the fact that it is not documented as the optimistically concurrent Remove method of ConcurrentDictionary, so http://msdn.microsoft.com/en-us/library/dd287153.aspx just duplicates the ICollection boilerplate, and the How to: Add and Remove Items from a ConcurrentDictionary does not mention that method either.
Does anyone know if that's the way to go, or is there some other method that I'm missing?
Though it is not an official document, this MSDN blog post can be helpful. The gist of that article: casting to ICollection and calling its Remove method, just as described in the question, is the way to go.
Here's a snippet from the above blog post, which wraps it into a TryRemove extension methods:
public static bool TryRemove<TKey, TValue>(
this ConcurrentDictionary<TKey, TValue> dictionary, TKey key, TValue value)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
return ((ICollection<KeyValuePair<TKey, TValue>>)dictionary).Remove(
new KeyValuePair<TKey, TValue>(key, value));
}
If you don't need all the bells & whistles of ConcurrentDictionary, you can just declare your type as an IDictionary.
public class ClassThatNeedsDictionary
{
private readonly IDictionary<string, string> storage;
public ClassThatNeedsDictionary()
{
storage = new ConcurrentDictionary<string, string>();
}
public void TheMethod()
{
//still thread-safe
this.storage.Add("key", "value");
this.storage.Remove("key");
}
}
I find this useful in situation in which you only need to add and remove, but still want a thread-safe iteration.
Related
If I instantiate a new Dictionary I can pass in many values:
Dictionary<string, string> data = new Dictionary<string, string>(){
{ "Key1", "Value1" },
{ "Key2", "Value2" },
{ "Key3", "Value3" },
{ "Key4", "Value4" },
{ "Key5", "Value5" },
}
However, if I already have a Dictionary, such as when it is passed in a parameter, I'm required to call Add for each key-value pair:
data.Add("Key1", "Value1");
data.Add("Key2", "Value2");
data.Add("Key3", "Value3");
data.Add("Key4", "Value4");
data.Add("Key5", "Value5");
I'm wondering if there's a "shorthand" method for adding in a large number of values to an existing Dictionary at one time - preferably natively? An authoritative "no" is welcome if that be the case.
Not as clean as I'm looking for, but these are the two alternatives I know.
This one allows passing many values at once, but requires creating a new Dictionary rather than updating the existing one:
Dictionary<string, string> newData = new Dictionary<string, string>(data)
{
{ "Key6", "Value6"},
{ "Key7", "Value7"},
{ "Key8", "Value8"},
};
It's also possible to create an extension method, but this still calls Add for each row:
public static void AddMany<Tkey, TValue>(this Dictionary<Tkey, TValue> dict, Dictionary<Tkey, TValue> toAdd)
{
foreach(KeyValuePair<Tkey, TValue> row in toAdd)
{
dict.Add(row.Key, row.Value);
}
}
An authoritative "no" is welcome if that be the case.
That be the case.
No, there is not an AddRange or equivalent because there is no practical way to add multiple items to a dictionary at one time. It makes sense for a List to add multiple items at once because they can get copied into the internal array in one command.
For a Dictionary, the hash code of each item must be computed to determine what "bucket" the value will get stored in, so there is by necessity a need to iterate over each item. Thus an AddRange method or its equivalent would at best be syntactic sugar. At worst, one would need to define what would happen if any item in the list already existed. Would it throw an exception? If so, would items that were added before the duplicate stay in the dictionary? If not, would it silently skip the item or replace the duplicate?
These are questions that have no intuitively correct answer and thus have not been pre-defined.
If you frequently need to add multiple items to your dictionary you could make an extension method
public static class DictionaryExtensions
{
public static void AddRange<TKey, TValue>(this Dictionary<TKey, TValue> dic, List<KeyValuePair<TKey, TValue>> itemsToAdd)
{
itemsToAdd.ForEach(x => dic.Add(x.Key, x.Value));
}
}
The above would be fine for bulk adding known-unique items. If you need to be concerned about dupes then you'd want to add sanity checks and perhaps return a list of bools to let you know which succeeded .. but at that point you might as well forego the extension method since much of the convenience would be lost.
You can make an extension to achieve this task.
public static class DictionaryHelper
{
public static Dictionary<TKey, TValue> AddRange<TKey, TValue>(this Dictionary<TKey, TValue> destination, Dictionary<TKey, TValue> source)
{
if (destination == null) destination = new Dictionary<TKey, TValue>();
foreach (var e in source)
{
if (!destination.ContainsKey(e.Key))
destination.Add(e.Key, e.Value);
destination[e.Key] = e.Value;
}
return destination;
}
}
This is a generic function that will accept another dictionary.
I have a tree of model object which I am displaying in a TreeView using a hierarchical data template. Each model object is converted on the fly to a ViewModel object using a ValueConverter, but the Model's properties are still bound to for the child items in the hierarchical data template.
The problem I have is that the Model objects store their children in dictionaries, and it's specifically the values, rather than the keys that I'm interested in client side. The Dictionary is not Observable, so what I am looking for is - in an ideal world - a way to wrap the Dictionary (or perhaps more specifically the internal ValueCollection that the Dictionary uses on the "Values" property, in order to make it observable.
I've delved into the source of the Dictionary to see if there are any hidden hooks I could reflect, but I can't see anything.
Anyone have a suggestion?
Edit:
The behaviour I want is effectively this:
var nonObservable = new Dictionary<Guid, object>();
var observableDictionary = new ObservableDictionary<Guid, object>(nonObservable);
observableDictionary.CollectionChanged += //Some event handler
nonObservable.Add(Guid.NewGuid, new object());
When I add objects to the non-observable Dictionary, I want a collection changed event on the wrapper to fire. This will probably require some deep reflecting. It's a hacky approach that I would rather avoid, but I don't really like the alternatives either.
You could implement the IDictionary<TKey, TValue> interface. Internally, you'd use a Dictionary, so your class would act as a proxy between the client and the real dictionary. However, you'd also be raising events, like this:
public class ObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private IDictionary<TKey, TValue> _dictionary = //...
public event EventHandler<DictionaryChangedArgs> OnAdded;
public ObservableDictionary()
{
_dictionary = new Dictionary<TKey, TValue>();
}
//wrap an existing dictionary
public ObservableDictionary(IDictionary<Tkey, TValue> dictionary)
{
_dictionary = dictionary;
}
public void Add(TKey key, TValue val) {
_dictionary.Add(key, value);
if(OnAdded != null)
OnAdded(new DictionaryChangedArgs(key, value));
}
}
Edit
Updated the code to reflect your requirement: "wrap an existing dictionary".
The idea seems to be similar to the one presented on dav_i's link.
Many custom Enumerable extensions can be implemented in terms of other builtin operations - for example this trivial convenience method:
public static bool AnyOf<TElement>(this TElement item, IEnumerable<TElement> items)
{
return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item));
}
Now this will force any PLINQ query back to sequential operation even though PLINQ also has a Any - and is equivalent with just just a signature change:
public static bool AnyOf<T>(this T item, ParallelQuery<T> items)
{
return items.Any(a => EqualityComparer<T>.Default.Equals(a, item));
}
But duplicating it like this seems messy to me.
At first I thought something like the below might work, but of course it does not^ because extension methods are static methods and therefore the decision to call Enumerable.Any as opposed to ParallelQuery.Any is made at compile time based on signature.
public static bool AnyOf<TElement, TEnumerable>(this TElement item, TEnumerable items)
where TEnumerable : class, IEnumerable<TElement>
{
return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item));
}
I've come to the conclusion it's impossible without creating a copy of each method with a different signature, but maybe there's something I've missed. (Gee always with the impossible questions!)
Perhaps a better example of a helper that would benefit from parallelization (can obviously be chained, etc. ) is something like this.
public static IEnumerable<string> ToStrings(this IEnumerable<object> ienum)
{
return ienum.Select(a=> a.ToString());
}
^ Compiler error:
The type 'ParallelQuery<TElement>' cannot be used as type parameter
'TEnumerable' in the generic type or method
'AnyOf<TElement,TEnumerable>(TElement, TEnumerable)'. There is no
implicit reference conversion from 'ParallelQuery<TElement>' to
'IEnumerable<TElement>'
Also worth considering is that not all of the ParallelQuery/Enumerable methods are equivalent, even if they do compile.
I have done similar for writing IQueryable/IEnumerable extensions. Trying to factor out the common bits involved declaring static variable holding an Expression, and then referencing that expression from the two different versions of the function. I don't have the code anymore, and when I was done, it was very ugly and I wasn't satisfied with it. Here is a trivial example.
Expression<Func<PersonHistory, bool>> IsCurrent = (p) => p.Ends > DateTime.Now && p.Starts <= DateTime.Now;
//Then in each Extension method:
var query = db.PersonHistories.Where(IsCurrent);
Ultimately the level of de-duplication was not good at all, and would be made more complicated by generic parameters. Maybe this will give you an idea though.
Looking forward to seeing others ideas.
You could do this by using checked casting inside the method (i.e. runtime switching) like so:
public static bool AnyOf<TElement>(this TElement item, IEnumerable<TElement> items)
{
var parallelItems = items as ParallelQuery<TElement>
if(parallelItems != null)
{
return parallelItems.Any(a => EqualityComparer<TElement>.Default.Equals(a, item))
}
//other runtime checks
....
//else return default IEnumerable implementation
return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item));
}
I try to do static class, add to icollection but i got some issues i cant seem to overcome. that is how i get so i can pass a ICollection in the method? cause T is that say it can not be resolved.
and then i wonder is there a way to do AddRange on icollection?
i was thinking of something like this but maby i am way out of my mind with it?
public static ICollection<T> add(this IEnumerable<T> list)
{
ICollection<T> collection = null;
return collection.AddRange(list);
}
No, ICollection<T> doesn't have an AddRange method - and even if it did, you'd be trying to dereference null which will throw a NullReferenceException. You haven't specified a collection to add the list to... what exactly are you trying to do?
You could create (say) a new List<T> - and that has the benefit of already having a constructor which can take an IEnumerable<T>:
public static ICollection<T> Add<T>(this IEnumerable<T> list)
{
return new List<T>(list);
}
However, at that point you've really just reimplemented Enumerable.ToList() and given it a different return type...
If you want to add everything to an existing collection, you might want something like this:
public static ICollection<T> AddTo<T>(this IEnumerable<T> list,
ICollection<T> collection)
{
foreach (T item in list)
{
collection.Add(item);
}
return collection;
}
If I understand correctly you want to add a IEnumerable<T> to an empty collection.
Wouldn't it be easier to just do:
ICollection<MyObject> collection = new List<MyObject>(GetIEnumerableOfMyObject());
Or even:
ICollection<MyObject> collection = GetIEnumerableOfMyObject().ToList();
The other ways seem to assume that your ICollection is empty and/or your ICollection is a type of List. However, if you want AddRange, then you can Extend the ICollection class as follows:
public static void AddRange<T>(this ICollection<T> ic, IEnumerable<T> ie)
{
foreach (T obj in ie)
{
ic.Add(obj);
}
}
Note, however, that since List impliments ICollection, this may cause ambiguity when dealing directly with List objects (though I haven't tested yet if the compiler will be able to resolve it--my gut reaction is that it should, though, since AddRange is a member of List and the compiler will go through member functions first before looking at extensions, but if I'm wrong I'm sure someone will correct me).
Depending on the collection type of your source list an alternative approach is to use List(T).ForEach, as in:
List<string> source = ...
ICollection<string> dest = ...
source.Foreach(dest.Add);
However, the readability of this is easy to dispute.
I am using a ResourceDictionary, but I would like to be able to look up the value or the key with the other item. Each is always unique, so that is not a problem. Is there a type that has this double sided lookup feature?
Not built in, but this is pretty easy to write. I would probably implement IDictionary for this though... You would then dump the ResourceDictionary into your custom type.
public class DoubleLookup<TKey, TValue>
{
private IDictionary<TKey, TValue> keys;
private IDictionary<TValue, TKey> values;
//stuff...
public void Add(TKey key, TValue value)
{
this.keys.Add(key, value);
this.values.Add(value, key);
}
public TKey GetKeyFromValue(TValue value)
{
return this.values[value];
}
public TValue GetValueFromKey(TKey key)
{
return this.keys[key];
}
}
Be very careful when reversing the key/value relationship in a dictionary.
The contract of the dictionary guarantees that, for every value in the collection, there is exactly one key which maps to that value. The keys are unique. But the reverse is not true; for every distinct value, there can be many different keys mapping to that value.
In my own personal code library (written in Java, which is close enough), I have MultiMap class for just this kind of thing. Although the keys are unique, each key can be associated with multiple values. It's exactly identical to a Map>.
When I need to perform value-to-key lookups in a collection, I do something like this:
Map<K, V> lookupTable = ...;
MultiMap<V, K> reverseLookupTable = MapUtil.invert(lookupTable);
V value = ...;
if (reverseLookupTable.containsKey(value)) {
Set<K> keys = reverseLookupTable.get(value);
}
If you use something other than a MultiMap (like a HashMap or Dictionary) as your reverse-lookup table, you run the risk of losing some of your V->K mappings, unless you can guarantee that all keys AND all values in your collection are unique.
EDIT:
Oops. I just noticed that you said that all keys and values in your collection are unique. But I'll leave my answer here anyhow, as a warning for others reading this, who might not be able to provide the same guarantee.