Please see our constructive discussion with Sascha Lefévre in comments to Solution 1. It is not yet quite comprehensive, as not all variants of modification by key are accessible to the user. Also, exception information is not informative. It is important to remember that key and value types may be not well presentable as strings.
As I was the one who suggested most of improvements, but it wasn't enough, let me summarize it on more general solution:
using System.Collections.Generic;
public class DictionaryWrapper<KEY, VALUE> {
public enum ValueModificationResult {
Success,
KeyNotFound,
NoValueChangeNeeded,
}
Dictionary<KEY, VALUE> dictionary = new Dictionary<KEY, VALUE>();
public ValueModificationResult ModifyExceptionless(KEY key, VALUE value) {
VALUE oldValue;
if (dictionary.TryGetValue(key, out oldValue)) {
if (value.Equals(oldValue))
return ValueModificationResult.NoValueChangeNeeded;
dictionary[key] = value;
return ValueModificationResult.Success;
} else
return ValueModificationResult.KeyNotFound;
}
public bool ModifyCombined(KEY key, VALUE value) {
VALUE oldValue;
if (dictionary.TryGetValue(key, out oldValue)) {
bool result = !value.Equals(oldValue);
if (result)
dictionary[key] = value;
return result;
} else
throw new ValueModificationException<KEY, VALUE>(key, value);
}
public ValueModificationResult AddOrModify(KEY key, VALUE value) {
var result = ModifyExceptionless(key, value);
if (result == ValueModificationResult.KeyNotFound) {
dictionary.Add(key, value);
return ValueModificationResult.Success;
}
return result;
}
public static implicit operator Dictionary<KEY, VALUE>(DictionaryWrapper<KEY, VALUE> wrapper)
{ return wrapper.dictionary; }
}
public class ValueModificationException<KEY, VALUE> : System.ApplicationException {
internal ValueModificationException(KEY key, VALUE value) {
this.Key = key; this.Value = value;
}
public KEY Key { get; private set; }
public VALUE Value { get; private set; }
}
Usage:
class UsageSample {
static void Test() {
DictionaryWrapper<string, int> wrapper = new DictionaryWrapper<string,int>();
Dictionary<string, int> dictionary = wrapper;
dictionary.Add("1", 1);
var result = wrapper.AddOrModify("1", 2);
}
}
Note the use of private setters of exception properties (read-only from outside class) and
internal
constructor (try not to give more access then required). Also note some benefits of the
ModifyExceptionless
variant of the
Modify
method: it is more suitable for use in
AddOrModify
.
—SA