How can I make this Dictionary TryGetValue code more readable? - c#

I'd like to test if an id was not yet known or, if it is known, if the associated value has changed. I'm currently using code similar to this, but it is hard to understand for those not familiar with the pattern. Can you think of a way to make it more readable while keeping it short in LOC?
string id;
string actual;
string stored;
if (!someDictionary.TryGetValue (id, out stored) || stored != actual) {
// id not known yet or associated value changed.
}

You can write an extension method with a good name:
public static class Utility
{
public static bool ValueChangedOrUnknown(this Dictionary<string, string> dictionary, string id, string actual)
{
string stored = null;
return (!dictionary.TryGetValue(id, out actual) || stored != actual);
}
}
so later you can use
string id;
string actual;
if (someDictionary.ValueChangedOrUnknown(id, actual) {
// id not known yet or associated value changed.
}

So I would most probably break it up and give it meaningful names. This is more to read, but you don't need much to say in comments:
bool isKnown = someDictionary.TryGetValue (id, out stored);
// can only change when it is known
bool valueChanged = isKnown && stored != actual;
// quite self-explanatory, isn't it?
if (!isKnown || valueChanged)
{
}

wrap each part of the || into its own method or property, than you can write it like this
if ( IdIsNew() || IdChanged())

Duality.
if (!(someDictionary.TryGetValue (id, out stored) && stored == actual)) ...
Not sure if it is more readable though... but it's good to know.

It looks fine to me...reads as easy as any other 2 condition if statement. About the only thing I'd possibly change is to flip the negations for an early exit:
if (someDictionary.TryGetValue(id, out stored) && stored == actual) {
return;
}
// store new value
I don't see any confusion in it at all, have never thought of it as a particularly troublesome idiom, and humbly suggest that those C# devs confused by it get used to it. It's common, succint, and gives as many LOC to the problem as it deserves. Turning it into 10 lines of code makes it way too important.
If I used it often, an extension method named something like ContainsEqualValue would be appropriate - but I'd use the exact same code in the extension method as you have.

I'd prefer a new method:
public bool ShouldSetValue(Dictionary someDictionary, object id,object actualValue)
{
string stored;
if (someDictionary.TryGetValue (id, out stored))
{
if (stored != actualValue)
return true;
}
else
{
return true;
}
}
then in the existing method I'd just:
if (ShouldSetValue(someDictionary,id,actual))
{
someDictionary[id]=actual;
}

An extension method would be slick:
public static class DictionaryExtensions
{
public static bool ShouldAddValue<TKey, TValue>(this Dictionary<TKey, TValue> someDictionary, TKey id, TValue actual)
{
TValue stored;
return (!someDictionary.TryGetValue(id, out stored) || !stored.Equals(actual));
}
}
Usage:
someDictionary.ShouldAddValue("foo", "bar")

If you mean that you have to do this repeatedly, and it is long and ugly, abstract the logic to another class and use an extension method.
public static class DictionaryExtensions
{
public static DictionaryChecker<TKey,TValue> contains<TKey,TValue>(this IDictionary<TKey,TValue> dictionary, TValue value)
{
return new DictionaryChecker<TKey,TValue>(value, dictionary);
}
}
public class DictionaryChecker<TKey,TValue>
{
TValue value;
IDictionary<TKey,TValue> dictionary;
internal DictionaryChecker(TValue value, IDictionary<TKey, TValue> dictionary)
{
this.value = value;
this.dictionary = dictionary;
}
public bool For(TKey key)
{
TValue result;
return dictionary.TryGetValue(key, out result) && result.Equals(value);
}
}
Now replace your code with:
if(!someDictionary.contains(actual).For(id)){
// id not known yet or associated value changed.
}

public T GetValue(int id, object actual)
{
object stored;
if (someDictionary.TryGetValue (id, out stored) || stored == actual)
return stored;
return new object();
}

While I recognize that the "try" pattern is necessary, I dislike implementations which require an "out" parameter. It would seem much more useful have functions similar to TryGetValue:
TryGetDictValue(dictionary, key) returns null if key is not in dictionary
TryGetDictValue(dictionary, key, defaultValue) returns defaultValue if key is not in dictionary
TryGetDictValue(dictionary, key, valueReturningDelegate) invokes the supplied delegate if key is not in dictionary and returns its result
In every case, the return type of the result would be that of the dictionary's data.
It's too bad there's no way to sneak into a time machine and make such things be methods of Dictionary. On the other hand, one could implement them as static functions taking a dictionary as the first parameter.

Related

In-line TryGetValue in If conditon and evaluate it's Value

Is there any way how to write TryGetValue on one line in If condition. Normal way of calling TryGetValue would be:
string value;
Dictionary.TryGetValue("Key", out value);
If(value == "condition") { ... }
What I am looking for would be something like this.
If(Dictionary.TryGetValue("Key", out string) == "Condition") { ... }
I know that line wouldn't work, however it shows what is desired result.
Is there any way how to achieve this?
You need to use the returned bool first but then you can use the out parameter(with >= C# 7):
if (Dictionary.TryGetValue("Key", out string value) && value == "Condition")
{
//...
}
MSDN:
Starting with C# 7.0, you can declare the out variable in the argument
list of the method call, rather than in a separate variable
declaration.
If you're not using C#7 or you want it even shorter you could use this extension:
public static bool TryEvaluateValue<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<TValue, bool> evalValue)
{
TValue val;
if(!dict.TryGetValue(key, out val))
return false;
return evalValue(val);
}
Then your if-condition becomes:
if (Dictionary.TryEvaluateValue("Key", value => value == "Condition"))
{
//...
}

Convenience method to find or add value to generic dictionary

Many times over the years, I have needed code that does:
Find a value in a dictionary; if it is not there, add it to the dictionary (and return that new value).
For example:
// Only one per account, so loading can be efficiently managed.
// <AccountID, LCProfilePicture>
public readonly static Dictionary<int, LCProfilePicture> All = new Dictionary<int, LCProfilePicture>();
public static LCProfilePicture GetOrCreate( int accountID )
{
LCProfilePicture pic;
if (!All.TryGetValue( accountID, out pic )) {
pic = new LCProfilePicture( accountID );
All[ accountID ] = pic;
}
return pic;
}
Instead of having to write that boilerplate each time, I'd like to have a generic method that will do the work. How to do so in c#?
So far, I have thought of three ways to proceed:
Wrap the construction that will be needed if the dictionary does not already contain an object for the key, into an Action (or Func?). Then call that if necessary.
Require TValue to have a constructor of that form, and then somehow describe that requirement as a constraint on the generic method.
Define some interface that TValue has to satisfy, and somehow use that interface to write the generic method.
I think I know how to do #1, so will submit an answer doing so, as soon as I work out the details. UPDATE: I have now worked that out, and posted that as an answer.
But maybe #2 is possible? Then I could just add that constraint, and be done.
Pro: easier to use (don't have to wrap the construction into an Action or Func).
Con: Not as flexible (if have a TValue that does not have such a constructor, can't use this generic method).
(#3 seems less promising; I mention it for completeness.)
You can combine constraints of new() and an interface for setting the key, like this:
interface IWithKey<T> {
public T Key { get; set; }
}
static class DictExtensions {
public static TVal GetorCreate<TKey,TVal>(this IDictionary<TKey,TVal> d, TKey key) where TVal : new(), IWithKey<TKey> {
TVal res;
if (!d.TryGetValue(key, out res)) {
res = new TVal();
res.Key = key;
d.Add(key, res);
}
return res;
}
}
Since GetorCreate is an extension, you can use it as follows:
static LCProfilePicture GetOrCreatePic( int accountID ) {
return All.GetOrCreateEntry(accountID);
}
I noticed in your example you have a static dictionary
// Only one per account, so loading can be efficiently managed.
// <AccountID, LCProfilePicture>
public readonly static Dictionary<int, LCProfilePicture> All =
new Dictionary<int, LCProfilePicture>();
My first reaction to that is, since it is static, are you going to need it to be thread safe. If the answer is yes, maybe, or even no, then the answer might be, don't write it yourself, let Microsoft do it.
System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>
Which so happens to have 2 built in functions
TValue GetOrAdd(TKey key, TValue value)
TValue GetOrAdd(TKey key, Func<TKey, TValue> func)
And all of that done in a thread-safe manner.
The second one where the parameter is a Func is the maybe the answer you are looking for.
If you are set on simplifying the usage, I would argue against having the loading of the data be part of the TValue. That is mostly based on my own person preference to store POCO (Plain Old CLR Objects) as values is Dictionaries and not objects with State and Behavior.
I would instead, move the "loading/constructing/deserializing" behavior to another service and/or the Dictionary itself.
This example creates a base class that you inherit from
public abstract class SmartConcurrentDictionaryBase<TKey, TValue> :
System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>
{
public TValue GetOrAdd(TKey key) { return GetOrAdd(key, LoadNewValue); }
protected abstract TValue LoadNewValue(TKey key);
}
public class LCProfilePictureDictionary : SmartConcurrentDictionaryBase<int, LCProfilePicture>
{
protected override LCProfilePicture(int accountID)
{
return new LCProfilePicture(accountID);
}
}
// use is
// var pic = All.GetOrAdd(accountID);
This example is more of a reusable Dictionary object and takes in a Func as a constructor parameter, but could easily be changed to include an Interface where one of the functions on the interface match the pattern.
public class SimpleConcurrentDictionary<TKey, TValue> :
System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>
{
private readonly Func<TKey, TValue> _loadFunc;
public SimpleConcurrentDictionary(Func<TKey, TValue> loadFunc)
{
_loadFunc = loadFunc;
}
public TValue GetOrAdd(TKey key) { return GetOrAdd(key, _loadFunc); }
}
System.Reflection has a ConstructorInfo object and a GetConstructor method that can be used for this purpose. ConstructorInfo.Invoke returns an object of the type that you used to create your ConstructorInfo. If you went the reflection route, it would look something like this (not tested, but should be close):
//using System.Reflection;
public static TValue GetOrCreateEntry<TKey, TValue>(Dictionary<TKey, TValue> dict, TKey key)
{
TValue value;
if (!dict.TryGetValue(key, out value))
{
// not in dictionary
ConstructorInfo ctor = typeof(TValue).GetConstructor(new Type[] { typeof(TKey) });
if (ctor != null)
{
// we have a constructor that matches the type you need
value = (TValue)ctor.Invoke(new object[] { key });
dict[key] = value;
return value;
}
else
throw new NotImplementedException(); // because the TValue type does not implement the constructor you anticipate
}
// we got it from dictionary, so just return it
return value;
}
Solution #1 (most general):
public static TValue GetOrCreateEntry<TKey, TValue>( Dictionary<TKey, TValue> dict, TKey key, Func<TValue> creator )
{
TValue value;
if (!dict.TryGetValue( key, out value )) {
value = creator();
dict[ key ] = value;
}
return value;
}
Example usage:
static LCProfilePicture GetOrCreatePic( int accountID )
{
return GetOrCreateEntry<int, LCProfilePicture>( All, accountID, () => new LCProfilePicture( accountID ) );
}
Solution #2 (for TValues that remember their key):
public static TValue GetOrCreateEntry<TKey, TValue>( Dictionary<TKey, TValue> dict, TKey key, Func<TKey, TValue> creator )
{
TValue value;
if (!dict.TryGetValue( key, out value )) {
value = creator(key);
dict[ key ] = value;
}
return value;
}
Example usage:
static LCProfilePicture GetOrCreatePic( int accountID )
{
return GetOrCreateEntry<int, LCProfilePicture>( All, accountID, key => new LCProfilePicture( key ) );
}
Comparison of Solution #1 and Solution 2:
Solution #1 is more general - it can be used even for TValues that don't need to know about the key.
Solution #2 is cleaner style, for TValues that do retain a reference to the key.
Two reasons #2 is preferable, where appropriate:
Reason #1: Solution #1 has the possibility of abuse: consider the case where TValue has two constructors, a parameterless one, and one that takes key as a parameter. An inexperienced programmer might use Solution #1 like this:
static LCProfilePicture GetOrCreatePic( int accountID )
{
// OOPS, programmer has not set the key field to "accountID".
return GetOrCreateEntry<int, LCProfilePicture>( All, accountID, () => new LCProfilePicture() );
}
If the lead programmer / architect wants to avoid that possibility, omit Solution #1, and only offer #2. In that case, the attempted usage won't compile, because there is no matching constructor.
Reason #2: Using Solution #1 requires including a second copy of the key in the usage, if TValue needs to capture it. This unnecessarily encapsulates the key in the Func instance, and could lead to accidentally referring to a different key, e.g.:
//...
int keyA;
int keyB;
// OOPS, programmer referred to the wrong key the second time.
// Maybe copy/pasted code, and only changed it in the first location, not realizing it is used in two places.
var valA = GetOrCreateEntry<int, LCProfilePicture>( All, keyA, () => new LCProfilePicture( keyB) );
enter code here

Add to Collection if Not Null

I have a very large object with many nullable-type variables. I also have a dictionary which I want to fill up with this object's non-null variables.
The code will look something like this
if (myObject.whatever != null)
{
myDictionary.Add("...",myObject.whatever);
}
if (myObject.somethingElse != null)
{
myDictionary.Add("...",myObject.somethingElse);
...
EDIT (Sorry messed up the code)
When we repeat this for the umpteenth time we get a mess of very long code. Is there some shorter way I could write this mess? I know about the Conditional Operator (aka ?) but that's just for assignments. Is there something like that for adding to a collection?
How about an extension method for your dictionary?
public static void AddIfNotNull<T,U>(this Dictionary<T,U> dic, T key, U value)
where U : class {
if (value != null) { dic.Add(key, value); }
}
You could then do this:
myDictionary.AddIfNotNull("...",myObject.whatever);
I'd recommend writing an extension method:
public static class MyExtensions
{
public static void AddIfNotNull<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
{
if ((object)value != null)
dictionary.Add(key, value);
}
}
Using (object)value != null ensures that this works as you'd expect with nullable types, (e.g. int?) value types, (e.g. int) and reference types (e.g. SomeClass). If you compare it to default(TValue), then an int of 0 will not be added, even though it's not null. If you include a TValue : class requirement, you can't use Nullable<T> as the type, which it sounds like is your most common usage.
You can make a method that hides your if:
AddIfNotNull(myDictionary, "...", myObject.whatever);
private static void AddIfNotNull<K,T>(
IDictionary<K,T> myDictionary
, K key
, T value) {
if (value != default(T)) {
myDictionary.Add(key, value);
}
}
You can earn some "points for style" by making the method an extension (you need to add it to a static class then):
private static void AddIfNotNull<K,T>(
this IDictionary<K,T> myDictionary
, K key
, T value) {
if (value != default(T)) {
myDictionary.Add(key, value);
}
}
myDictionary.AddIfNotNull(myDictionary, "...", myObject.whatever);
If you know that you are inserting only reference type objects, replace default(T) with null and add a class T constraint to the generic.
public void addToDict(string ?myObj, Dictionary<,> myDict) {
if (myObj != null)
myDict.Add("...", myObj);
}
addToDict(myObject.whatever, myDict);
addToDict(myObject.somethignElse, myDict);
etc

Caching return value of an extension method

Here is pseudo code of what this would look like if I could modify the class in question
public class Foo
{
private TheDataType _Data;
public TheDataType GetData()
{
if (_Data != null)
return _Data;
// fetch/generate data
return _Data;
}
}
How do I turn this into an extension method? The definition/scope of the _Data is what bothers me...
================================================
This is probably the closest to what I want, but feel like an overkill for something so simple
public static class FooExtensions
{
private static ConcurrentDictionary<Foo,TheDataType> DataCache = new ConcurrentDictionary<Foo,TheDataType>();
public static TheDataType GetData(this Foo foo)
{
TheDataType data;
if (DataCache.TryGetValue(foo, out data))
return data
// fetch/generate data
DataCache.Add(foo, data);
return data;
}
}
You could have your extension method utilize a cache manager class (custom or built into the framework) which kept track of the data based on some unique identifier for the instance:
public static DataType GetData( this Foo obj )
{
DataType retVal;
// this sample doesn't show any locking, i.e. it is not thread safe
// if cache manager contains data return from there
if( CacheManager.HasData( obj.UniqueId ) )
{
retVal = CacheManager.GetData( obj.UniqueId );
}
else
{
// otherwise invoke a method on obj and add to cache
retVal = obj.GetData();
CacheManager.Add( obj.UniqueId, retVal );
}
return retVal;
}
However, this strikes me as a potential misuse of an extension method, even though it's syntactically clean. It would depend on the context in which it is used and on how obvious the side effects were. For example this would be really hard for another developer to troubleshoot if they didn't know that GetData() was using a cache, the cache expiration wasn't clear, etc.
This is a good fit for function caching, described in this blog post of mine. The idea is to take a function with one argument and turn it into another function which caches the result of the original one:
public static Func<TKey, TValue> Cached<TKey, TValue>(this Func<TKey, TValue> valueFunction)
{
var cache = new Dictionary<TKey, TValue>();
return key =>
{
TValue value;
if(!cache.TryGetValue(key, out value))
{
value = valueFunction(key);
cache[key] = value;
}
return value;
};
}
The cache dictionary gets embedded inside the returned closure, so it will have the same lifetime of the function we return.
You would use it by replacing the original call to get the data with the new function:
public class UsesTheDataType
{
private readonly Func<Foo, TheDataType> _generateData;
public UsesTheDataType()
{
_generateData = GenerateData;
_generateData = _generateData.Cached();
}
public void UseTheDataType(Foo foo)
{
var theDataType = _generateData(foo);
// theDataType is either a new value or cached value
}
private TheDataType GenerateData(Foo foo)
{
// Only called the first time for each foo
}
}
The nice part here is that the caching is written once for all functions, so you can reuse the same approach no matter what you have to cache. This also avoids possible memory leaks resulting from the use of a static cache.
This can also be done in a thread-safe manner. See the second post in the series for a walkthrough.
I'm not quite sure what you are trying to accomplish, but if I follow, it would look something like.
public static class FlargExtensions
{
private static Flarg flarg;
public static Flarg GetData(this Flarg flarg)
{
if (FlargExtensions.flarg != null)
return Class1.flarg;
FlargExtensions.flarg = new Flarg();
return FlargExtensions.flarg;
}
}
public class Flarg
{
}

Need an IDictionary<TKey,TValue> implementation that will allow a null key

Basically, I want something like this:
Dictionary<object, string> dict = new Dictionary<object, string>();
dict.Add(null, "Nothing");
dict.Add(1, "One");
Are there any built into the base class library that allow this? The preceding code will throw an exception at runtime when adding the null key.
You could avoid using null and create a special singleton value class that does the same thing. For example:
public sealed class Nothing
{
public static readonly Nothing Value = new Nothing();
private Nothing() {}
}
Dictionary<object, string> dict = new Dictionary<object, string>();
dict.add(Nothing.Value, "Nothing");
dict.add(1, "One");
This approach will fail to work if you intend to make your collection more strongly typed - let's say for example you want the key to be a string. Since string is sealed you can't inherit from it to create a "special value" substitute for null. Your alternatives become a bit more complicated. You could:
Create some special constant value to represent the "empty" / "null" case. Kind of hacky and definitely a path to confusion. This can be a viable approach if the dictionary is completely private to some implementation class and you can write some Encode/Decode utility methods to avoid spreading the knowledge of how you translate keys all over the place.
Create your own implementation of IDictionary that internally delegates to a Dictionary<> instance - except for the case of null. This violates the documented expectations for the IDictionary<> interface which does say that null keys should throw an exception. But you may be able to get away with it if it's the only way to solve your real problem. This only works if you own and create the dictionary instance.
Find a way to solve your problem without storing a "null" key in the dictionary. For example, consider not populating the null key in the dictionary and having some special case logic to deal with it. Keys have to be hashable and comparable to work with the underlying implementation, which is why null is prohibited normally.
As an aside, does your dictionary key really need the key to be object? This can lead to subtle bugs due to reference equality being used where you may have intended Equals() to be evaluated as the basis for comparison.
How about this?
public class NullableDictionnary<T1, T2> : Dictionary<T1, T2>
{
T2 null_value;
public T2 this[T1 key]
{
get
{
if (key == null)
{ return null_value; }
return base[key];
}
set
{
if (key == null)
{ null_value = value; }
else
{ base[key] = value; }
}
}
}
NameValueCollection can take a null key but it does not implement IDictionary. It would however be pretty easy to derive from DictionaryBase and provide Add/Remove/Indexers etc that simply replace null with something built in like:
class MyDictionary : DictionaryBase {
private readonly object nullKey = new object();
void Add(object key, string value) {
if ( key == null ) { key = nullKey; }
.. call base methods
}
}
You can simply use ValueTuple as a wrapper for key, for example:
Dictionary<ValueTuple<string?>, string>
No need for a different implementation of Dictionary.
Take a look at my answer here:
https://stackoverflow.com/a/22261282/212272
You will also be able to keep your dictionary strongly typed:
var dict = new Dictionary<NullObject<int?>, string>();
dict[1] = "one int";
dict[null] = "null int";
Assert.AreEqual("one int", dict[1]);
Assert.AreEqual("null int", dict[null]);
If key is enum, you can use not existing value instead of null like (YourEnum)(-1)
Does the key literally need to be NULL? The key in the collection works out to be an index. It doesn't make a lot of sense to me to have NULL for an index in a collection.
Maybe create a new class
public class ObjectEntry
{
public object objRef;
public string desc;
public ObjectEntry(object objectReference)
{
objRef = objectReference;
if (objRef = null) {desc = "Nothing";}
else {desc = objRef.Description;} //or whatever info you can get from a proper objRef value
}
}
newObj = new ObjectEntry(null);
dict.add(newObj, newObj.desc);
A slight variation on jestro's answer to make for a cleaner(to me) solution that makes it more explicit what you are trying to do. Obviously this could be extended as needed. But you get the picture, just make a wrapper.
public class NullDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
private TValue _default;
public new TValue this[TKey key]
{
get {
if(key == null)
{
return _default;
}
return _decorated[key];
}
}
private Dictionary<TKey, TValue> _decorated;
public NullDictionary( Dictionary<TKey,TValue> decorate, TValue defaultValue = default)
{
_decorated = decorate;
_default = defaultValue;
}
}

Categories