Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DotNETFrameworkNotesForProfessionals.pdf
Скачиваний:
32
Добавлен:
20.05.2023
Размер:
1.82 Mб
Скачать

Use the Remove method to remove a key and its associated value.

bool wasRemoved = dict.Remove(2);

Executing this code removes the key 2 and it's value from the dictionary. Remove returns a boolean value indicating whether the specified key was found and removed from the dictionary. If the key does not exist in the dictionary, nothing is removed from the dictionary, and false is returned (no exception is thrown).

It's incorrect to try and remove a key by setting the value for the key to null.

dict[2] = null; // WRONG WAY TO REMOVE!

This will not remove the key. It will just replace the previous value with a value of null.

To remove all keys and values from a dictionary, use the Clear method.

dict.Clear();

After executing Clear the dictionary's Count will be 0, but the internal capacity remains unchanged.

Section 4.10: ContainsKey(TKey)

To check if a Dictionary has an specifique key, you can call the method ContainsKey(TKey) and provide the key of TKey type. The method returns a bool value when the key exists on the dictionary. For sample:

var dictionary = new Dictionary<string, Customer>()

{

{"F1", new Customer() { FirstName = "Felipe", ... } }, {"C2", new Customer() { FirstName = "Carl", ... } }, {"J7", new Customer() { FirstName = "John", ... } }, {"M5", new Customer() { FirstName = "Mary", ... } },

};

And check if a C2 exists on the Dictionary:

if (dictionary.ContainsKey("C2"))

{

// exists

}

The ContainsKey method is available on the generic version Dictionary<TKey, TValue>.

Section 4.11: ConcurrentDictionary augmented with Lazy'1 reduces duplicated computation

Problem

ConcurrentDictionary shines when it comes to instantly returning of existing keys from cache, mostly lock free, and contending on a granular level. But what if the object creation is really expensive, outweighing the cost of context switching, and some cache misses occur?

If the same key is requested from multiple threads, one of the objects resulting from colliding operations will be eventually added to the collection, and the others will be thrown away, wasting the CPU resource to create the object and memory resource to store the object temporarily. Other resources could be wasted as well. This is really bad.

GoalKicker.com – .NET Framework Notes for Professionals

17

Solution

We can combine ConcurrentDictionary<TKey, TValue> with Lazy<TValue>. The idea is that ConcurrentDictionary GetOrAdd method can only return the value which was actually added to the collection. The loosing Lazy objects could be wasted in this case too, but that's not much problem, as the Lazy object itself is relatively unexpensive. The Value property of the losing Lazy is never requested, because we are smart to only request the Value property of the one actually added to the collection - the one returned from the GetOrAdd method:

public static class ConcurrentDictionaryExtensions

{

public static TValue GetOrCreateLazy<TKey, TValue>( this ConcurrentDictionary<TKey, Lazy<TValue>> d, TKey key,

Func<TKey, TValue> factory)

{

return d.GetOrAdd(

key, key1 =>

new Lazy<TValue>(() => factory(key1), LazyThreadSafetyMode.ExecutionAndPublication)).Value;

}

}

Caching of XmlSerializer objects can be particularly expensive, and there is a lot of contention at the application startup too. And there is more to this: if those are custom serializers, there will be a memory leak too for the rest of the process lifecycle. The only benefit of the ConcurrentDictionary in this case is that for the rest of the process lifecycle there will be no locks, but application startup and memory usage would be inacceptable. This is a job for our ConcurrentDictionary, augmented with Lazy:

private ConcurrentDictionary<Type, Lazy<XmlSerializer>> _serializers = new ConcurrentDictionary<Type, Lazy<XmlSerializer>>();

public XmlSerializer GetSerialier(Type t)

{

return _serializers.GetOrCreateLazy(t, BuildSerializer);

}

private XmlSerializer BuildSerializer(Type t)

{

throw new NotImplementedException("and this is a homework");

}

GoalKicker.com – .NET Framework Notes for Professionals

18