Is there any general dictionary where trying to get a nonexistent key will return null?

It really annoys me that I should use .ContainsKey instead of just doing value==null in the dictionary. Real life example:

 var dictionary = new Dictionary<string, FooBar>(); var key = "doesnt exist"; var tmp = dictionary[key] ?? new FooBar(x, y); 

Instead, I have the following options:

 var key = "doesnt exist"; FooBar tmp = null; if (dictionary.ContainsKey(key)) { tmp = dictionary[key]; } else { tmp = new FooBar(x, y); } 

Or that:

 FooBar tmp = null; if (!Dictionary.TryGetValue(key, out tmp)) { tmp = new FooBar(x, y); } 

For me, this code is very detailed. Is there a built-in generic class that implements IDictionary (or otherwise allows access to the key type) but does not throw an exception when I try to find the key and return null instead?

+4
source share
3 answers

The problem is that Dictionary<TKey, TValue> allows you to store null as a value, so you don’t know if the key existed or just had null . Another problem is that null is only applicable to TValue types that are reference types (or Nullable<T> ).

Now that you have said, you yourself can write an extension method:

 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; } } 

So you can query your dictionary as follows:

 var sample = new Dictionary<int, string> { {1, "One"}, {2, "Two}, {3, "Three"} }; var willBeNull = sample.SafeGet(4); var willBeHi = sample.SafeGet(4, "HI!"); 

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

Again, however, you can create two forms where TValue limited to a class and one to a struct , which allows you to return Nullable<T> value types ...

+8
source

For a generic collection, null not always a valid value, and you cannot write a generic method that returns null . it should be the default (T).

You can easily create a utility method that returns the default value (T) if you are sure that you will not use it as a value

+2
source

If you renew, you must pass a default value each time.
It may be what you want.
You can implement the dictionary and pass the default value to ctor.

 public class DictionaryWithDefault<T1,T2> : Dictionary<T1,T2> { private T2 t2Default; public new T2 this[T1 t1] { // indexer - if the key is not present return the default get { T2 t2t; return TryGetValue(t1, out t2t) ? t2t : t2Default; } set { base[t1] = value; } } public DictionaryWithDefault(T2 _t2) { this.t2Default = _t2; } } 

If you want the Dictionary not to allow null, you override Add.

Borrowed some syntax from JamesMH +1

Where I use something like this is a compound key dictionary.

If this suffers, if you change the default value, then it will change the value of t2Default.
I'm working on it.
If T2 is a value type, then this works.
If T2 is a reference type, then you will need to make a deep copy, and this is not a hassle.

0
source

Source: https://habr.com/ru/post/1440408/


All Articles