-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
Scenario
In almost every app or library I write I almost always end up needing to write code like this, in at least one place:
SomeClass returnValue;
return DictionaryOfSomeClass.TryGetValue(someKey, out returnValue) ? returnValue : null;The reason that the IDictionary<TKey, TValue> contract throws from its indexer for a non-existent key are well-known: an alternative behavior of returning null is nonsensical if TValue is a value type. Returning default(TValue) would work, but would clearly be a misleading behavior.
But with dictionaries of class-types it is often desirable and expected to return null for a non-existent key.
Proposal
namespace System.Collections.Generic
{
public class Dictionary<TKey, TValue>
{
public TValue GetValueOrDefault(TKey key);
public TValue GetValueOrDefault(TKey key, TValue defaultValue);
}
public static class CollectionExtensions
{
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key);
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue);
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key);
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue);
}
}Notes:
- There will be source-compile problem with ambiguity in all projects that already have such custom extension method
GetValueOrDefaultonIDictionaryorIReadOnlyDictionary. Which is general problem for any extension method we add into CoreFX.
Original Proposal - replaced by the one above
I propose the following extension method (I don't like the name GetValueNoThrow, so that can be ignored for now). Please note that it applies only when TValue is a class, so it does not violate any behavior for value types.
public static class ClassyDictionaryExtensions
{
public static TValue GetValueNoThrow_Ignore_The_Name<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
where TValue : class
{
if (dictionary == null)
{
throw new ArgumentNullException(nameof(dictionary));
}
TValue value;
dictionary.TryGetValue(key, out value);
return value;
}
}The new code would end up with one very-easy-to-read line of code:
return DictionaryOfSomeClass.GetValueNoThrow(someKey);Discussion
Would others find such an extension method useful?