Is There an Idictionary Implementation That, on Missing Key, Returns the Default Value Instead of Throwing

Is there an IDictionary implementation that, on missing key, returns the default value instead of throwing?

Indeed, that won't be efficient at all.

As per comments, in .Net Core 2+ / NetStandard 2.1+ / Net 5, MS added the extension method GetValueOrDefault()

For earlier versions you can write the extension method yourself:

public static TValue GetValueOrDefault<TKey,TValue>
(this IDictionary<TKey, TValue> dictionary, TKey key)
{
TValue ret;
// Ignore return value
dictionary.TryGetValue(key, out ret);
return ret;
}

Or with C# 7.1:

public static TValue GetValueOrDefault<TKey,TValue>
(this IDictionary<TKey, TValue> dictionary, TKey key) =>
dictionary.TryGetValue(key, out var ret) ? ret : default;

That uses:

  • An expression-bodied method (C# 6)
  • An out variable (C# 7.0)
  • A default literal (C# 7.1)

Dictionary returning a default value if the key does not exist

TryGetValue will already assign the default value for the type to the dictionary, so you can just use:

dictionary.TryGetValue(key, out value);

and just ignore the return value. However, that really will just return default(TValue), not some custom default value (nor, more usefully, the result of executing a delegate). There's nothing more powerful built into the framework. I would suggest two extension methods:

public static TValue GetValueOrDefault<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
TValue defaultValue)
{
return dictionary.TryGetValue(key, out var value) ? value : defaultValue;
}

public static TValue GetValueOrDefault<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
Func<TValue> defaultValueProvider)
{
return dictionary.TryGetValue(key, out var value) ? value : defaultValueProvider();
}

(You may want to put argument checking in, of course :)

Is there an IDictionary implementation that, on missing key, returns the default value instead of throwing?

Indeed, that won't be efficient at all.

As per comments, in .Net Core 2+ / NetStandard 2.1+ / Net 5, MS added the extension method GetValueOrDefault()

For earlier versions you can write the extension method yourself:

public static TValue GetValueOrDefault<TKey,TValue>
(this IDictionary<TKey, TValue> dictionary, TKey key)
{
TValue ret;
// Ignore return value
dictionary.TryGetValue(key, out ret);
return ret;
}

Or with C# 7.1:

public static TValue GetValueOrDefault<TKey,TValue>
(this IDictionary<TKey, TValue> dictionary, TKey key) =>
dictionary.TryGetValue(key, out var ret) ? ret : default;

That uses:

  • An expression-bodied method (C# 6)
  • An out variable (C# 7.0)
  • A default literal (C# 7.1)

How can I change Dictionary so that it returns custom default value rather than throw exception if no such key?

You could make your own class which encapsulates a Dictionary<TKey,TValue>, and implements IDictionary<TKey,TValue>.

This will behave like a dictionary, but you can write the behavior to handle your non-existent key any way you wish.

However, you can't change the way the actual Dictionary<TKey,TValue> class functions.

How to get null instead of the KeyNotFoundException accessing Dictionary value by key?

In the end I came up with a variant using a deriving from dictionary class with explicit interface implementation:

public interface INullValueDictionary<T, U>
where U : class
{
U this[T key] { get; }
}

public class NullValueDictionary<T, U> : Dictionary<T, U>, INullValueDictionary<T, U>
where U : class
{
U INullValueDictionary<T, U>.this[T key]
{
get
{
U val;
this.TryGetValue(key, out val);
return val;
}
}
}

So it exposes the functionality I need the following way:

//create some dictionary
NullValueDictionary<int, string> dict = new NullValueDictionary<int, string>
{
{1,"one"}
};
//have a reference to the interface
INullValueDictionary<int, string> idict = dict;

try
{
//this throws an exception, as the base class implementation is utilized
Console.WriteLine(dict[2] ?? "null");
}
catch { }
//this prints null, as the explicit interface implementation
//in the derived class is used
Console.WriteLine(idict[2] ?? "null");

Is there any sort of generic dictionary where attempting to get a non-existent key will return null?

The problem is that Dictionary<TKey, TValue> allows you to store null as a value, thus you wouldn't know if the key didn't exist, or just had a value of null. The other problem is that null is only valid for TValue types that are reference types (or Nullable<T>).

Now, that said, you could write an extension method yourself to do so:

public static class DictionaryUtilities
{
public static TValue SafeGet<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue defaultIfNotFound = default(TValue))
{
TValue value;

return dict.TryGetValue(key, out value) ? value : defaultIfNotFound;
}
}

In this way, you could query your dictionary like this:

var sample = new Dictionary<int, string> { {1, "One"}, {2, "Two}, {3, "Three"} };

var willBeNull = sample.SafeGet(4);

var willBeHi = sample.SafeGet(4, "HI!");

Though, of course, the above code would return the default of value types if TValue was a value type (that is, if the value type was int, it would return 0 on not found, by default.)

Again, though, you could create two forms, one where TValue is constrained to class and one to struct that would allow you to return a Nullable<T> for value types...

ConcurrentDictionary cast to IDictionary, indexer for missing key no longer throws exception

From https://msdn.microsoft.com/en-us/library/system.collections.idictionary.item(v=vs.110).aspx :

The element with the specified key, or null if the key does not exist.

So this is expected behaviour.

This seems to be dangerous behavior: an explicit implementation should not vary so much from the regular public indexer, should it?

It darn well should when its documented as doing so, unless there's a very good reason not to (enough really for the documentation to be considered buggy).

So, if the only known type that I have is IDictionary, how can I check for the existence of a key short of looping through all the keys and comparing?

IDictionary.Contains though this is a nuisance (and a race in multi-threaded scenarios), which is why KeyNotFoundException and IDictionary<TKey, TValue>.TryGetValue were introduced with 2.0.

The lack of a TryGetValue method meant that in 1.1 the only way to have a test on an IDictionary for a key that may not be present without throwing was to know that null was never going to be added in there. This is far from ideal, so the generic equivalent changed that, but its too late to update IDictionary to match as all existing uses would be broken.

Alternative of ?? for non nullable types (e.g. when looking up dictionary keys)

You can replace if checking with ternary operator

 var value = someDictionary.TryGetValue(someKey, out var val) ? val : anotherValue;

a default value for a Dictionary in c#

Check if it exists, if not, return a default value:

Model.AnswserKeywordDictionary.ContainsKey("myKey")
? Model.AnswserKeywordDictionary["myKey"]
: "default"

You could also create an extension method for that:

    public static Dictionary<K, V> GetValueOrDefault<K, V>(this Dictionary<K, V> dictionary, K key, V defaultValue)
{
V val;
if (dictionary.TryGetValue(key, out val))
{
return val ?? defaultValue;
}

return defaultValue;
}

Use it like this:

Model.AnswserKeywordDictionary.GetValueOrDefault("myKey", "default")

Is there an IDictionary implementation that keeps the keys in the order they were added ? (NOT sorted order)

Could you perhaps just keep a List and a Dictionary that allows you to lookup where keys are in the list? That would allow you to get the key/value pairs in order of addition but still maintain O(1) lookup.



Related Topics



Leave a reply



Submit