Is there a way to check at compile time a dictionary's key uniqueness in a method scope when you add them with the Add() method?
Example: there are a bunch of payment solution providers (PayPal, PayEx, etc.) that give some sort of a status result when you query a transaction, lets say an integer. Since every PSP handles statuses differently, we have a fixed amount of system statuses (such as Pending, Aborted, Committed, etc.) that are mapped to the various status codes for each PSP.
public static class ResponseMapping
{
private static readonly Dictionary<int, PaymentResult> ResultMap;
static ResponseMapping()
{
ResultMap = new Dictionary<int, PaymentResult>();
ResultMap.Add(1, PaymentResult.LogonError);
ResultMap.Add(2, PaymentResult.Pending);
ResultMap.Add(9, PaymentResult.Ok);
// OH DEAR, THIS WILL BLOW UP
ResultMap.Add(1, PaymentResult.Something);
}
public static PaymentResult FindAppropriateResponse(int resultCode)
{
if (ResultMap.ContainsKey(resultCode))
{
return ResultMap[resultCode];
}
return PaymentResult.UnknownResult;
}
}
An easy shortcut would be to use the [] indexing notation to add each map, but with Add() you can avoid possibly overriding something that you didn't mean to.
Unfortunately, this way it blows up at runtime. Is there a technique that would make it blow up at compile time?
I don't think you can check for key existence at compile time. Instead you can use Dictionary.ContainsKey method like:
int key = 1; //your key
if(!ResultMap.ContainsKey(key))
{
ResultMap.Add(key, PaymentResult.Something);
}
You can use ContainsKey:
if(!ResultMap.ContainsKey(1))
{
ResultMap.Add(1, PaymentResult.Something);
}
or TryGetValue:
obj item;
if(!ResultMap.TryGetValue(1, out item))
ResultMap.Add(1, PaymentResult.Something);
If you really really need a dictionary object I don't think you can do it at compile time and can sort of fake it with a unit test. But if you just want a look up, use a switch.
public static PaymentResult FindAppropriateResponse(int resultCode)
{
switch(resultCode)
{
case 1:
return PaymentResult.LogonError;
case 2:
return PaymentResult.Pending;
case 3:
return PaymentResult.Ok;
default:
return PaymentResult.UnknownResult;
case 1: // Does blow up at compile time
return PaymentResult.Something;
}
}
You could define a method which you use instead of Add.
It will add the value if not exists or replace it if it exists.
private void Add(Dictionary<int, PaymentResult> PaymentResults, int index, PaymentResult pResult)
{
if(PaymentResults.ContainsKey(index))
{
PaymentResults[index] = pResult;
}
else
{
PaymentResults.Add(index, pResult);
}
}
And to use it
this.Add(ResultMap, 1, PaymentResult.LogonError);
This is related but not exactly. I had the problem of I wasn't sure if a key would exist or not, so I created a simple method.
private void AddKey(string key, string value)
{
if (!Dictionary.ContainsKey(key))
Dictionary.Add(key, value);
}
The just call AddKey(key,value);
Maybe this will help you some.
Or extend
public static class Extensions
{
public static bool Push<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue value)
{
try
{
if (dictionary.ContainsKey(key))
{
dictionary[key] = value;
}
else
{
dictionary.Add(key, value);
}
return true;
}
catch (Exception ex)
{
return false;
}
}
public static TValue Pull<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
{
try
{
return dictionary.ContainsKey(key) ? dictionary[key] : default(TValue);
}
catch (Exception ex)
{
return default(TValue);
}
}
}
Then you can do
ResultMap = new Dictionary<int, PaymentResult>();
ResultMap.Push(1, PaymentResult.LogonError); //1 -> PaymentResult.LogonError
ResultMap.Push(1, PaymentResult.Something); //1 -> PaymentResult.Something
Related
I kept googling for some time, and I found that the best way that enables you to have a list containing variables with a corresponding unique key is a HashTable or a Dictionary, but I didn't find anything that enables you to have automatic keys(of type integer). I want to call a function that adds an object(passed as a parameter) to the dictionary and returns the automatically generated key(int), and without any key duplicates. How could I accomplish this? I am completely struggling!
EDIT: To clarify things up. This is a server, and I want to assign a unique key for each client. If I use the maximum key value, this value will soon get to the int maximum value on large servers. Because if a client connects then disconnects he leaves behind an unused value which should be reused in order to avoid reaching a very high key maximum value.
The following should do and it reuses freed up keys:
internal class AutoKeyDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
{
private readonly Dictionary<TKey, TValue> inner;
private readonly Func<TKey, TKey> incrementor;
private readonly Stack<TKey> freeKeys;
private readonly TKey keySeed;
private TKey currentKey;
public AutoKeyDictionary(TKey keySeed, Func<TKey, TKey> incrementor)
{
if (keySeed == null)
throw new ArgumentNullException("keySeed");
if (incrementor == null)
throw new ArgumentNullException("incrementor");
inner = new Dictionary<TKey, TValue>();
freeKeys = new Stack<TKey>();
currentKey = keySeed;
}
public TKey Add(TValue value) //returns the used key
{
TKey usedKey;
if (freeKeys.Count > 0)
{
usedKey = freeKeys.Pop();
inner.Add(usedKey, value);
}
else
{
usedKey = currentKey;
inner.Add(usedKey, value);
currentKey = incrementor(currentKey);
}
return usedKey;
}
public void Clear()
{
inner.Clear();
freeKeys.Clear();
currentKey = keySeed;
}
public bool Remove(TKey key)
{
if (inner.Remove(key))
{
if (inner.Count > 0)
{
freeKeys.Push(key);
}
else
{
freeKeys.Clear();
currentKey = keySeed;
}
return true;
}
return false;
}
public bool TryGetValue(TKey key, out TValue value) { return inner.TryGetValue(key, out value); }
public TValue this[TKey key] { get {return inner[key];} set{inner[key] = value;} }
public bool ContainsKey(TKey key) { return inner.ContainsKey(key); }
public bool ContainsValue(TValue value) { return inner.ContainsValue (value); }
public int Count { get{ return inner.Count; } }
public Dictionary<TKey,TValue>.KeyCollection Keys { get { return inner.Keys; } }
public Dictionary<TKey, TValue>.ValueCollection Values { get { return inner.Values; } }
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return inner.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)inner).GetEnumerator(); }
}
Disclaimer: I haven't tested this code, it could have a few pesty bugs of little importance, the general approach is sound.
Write a class which does this. Something like this:
class AutoIndexDictionary : IEnumerable<Whatever>
{
private readonly Dictionary<int, Whatever> myDict = new Dictionary<int, Whatever>();
private int currentIndex = 0;
public int Add(Whatever item)
{
var myIndex = currentIndex
myDict.Add(myIndex, item);
currentIndex ++;
return myIndex;
}
public void Remove(int index)
{
myDict.Remove(index);
}
// implement IEnumerable, indexer etc.
// ...
}
Create a method that gets the max key value from the dictionary using LINQ, adds 1 to it and then uses that as the key for the value you would like to add, like this:
public void AddToMyDictionary(string value)
{
int NextKey = MyDictionary.Keys.Max() + 1;
MyDictionary.Add(NextKey, value);
}
Obviously, this assumes your dictionary is a Dictionary<int, string>, but you can obviously modify for your purposes.
If you want to re-use keys that have been removed, store the next index when something is added / removed.
private int NextKey = 0;
public int AddToMyDictionary(string value)
{
int currentKey = NextKey;
MyDictionary.Add(currentKey, value);
NextKey = MyDictionary.Keys.Max() + 1;
return currentKey;
}
public void RemoveFromMyDictionary(int key)
{
MyDictionary.Remove(key);
NextKey = key;
}
This is what int Object.GetHashCode() is for.
Wouldn't a List do what you say, without any additional overhead? You call it a "unique integer key", but in List terminology, that's simply called an "index".
If you really wanted a custom function to add a value and get a key all in one step, you could inherit from List<T>, like so:
class MyCustomList<T> : List<T>
{
//Not thread-safe
public int AddAndGetKey(T valueToAdd)
{
Add(valueToAdd);
return LastIndexOf(valueToAdd);
}
}
I use LastIndexOf() because the list may include duplicate values and adding to the list always adds to the end. So this should work unless you get into multithreaded situations where you'd have to add-and-get-index in one atomic operation. (Alternately maybe you could add an extension method to List<T>.)
The advantage of using a List is that there would be no gaps in keys. On the flipside, removing an item in the middle would change the key of every item after it. But I guess it depends what behavior you're looking for.
Given the additional information provided in your edit then i don't think int is the correct datatype for you, you shouldn't reuse ID's the way you are describing as if a client with an ID gets disconnected but don't realise then you could have 1 ID in use by 2 clients. change your datatype to Guid then when you get a new client give it a key of Guid.NewGuid() and the chance of duplicate keys drops as close as possible to 0
I like Stefan Steinegger's solution. Here is an alternative that uses a List<> behind the scenes, but ensures the List<> is never removed from:
class AutoKeyDictionary<TValue> : IEnumerable<TValue> where TValue : class
{
readonly List<TValue> list = new List<TValue>();
public int Add(TValue val)
{
if (val == null)
throw new ArgumentNullException(nameof(val), "This collection will not allow null values.");
list.Add(val);
return list.Count - 1;
}
public void RemoveAt(int key)
{
// do not remove ('list.Count' must never decrease), overwrite with null
// (consider throwing if key was already removed)
list[key] = null;
}
public TValue this[int key]
{
get
{
var val = list[key];
if (val == null)
throw new ArgumentOutOfRangeException(nameof(key), "The value with that key is no longer in this collection.");
return val;
}
}
public int NextKey => list.Count;
public int Count => list.Count(v => v != null); // expensive O(n), Linq
public bool ContainsKey(int key) => key >= 0 && key < list.Count && list[key] != null;
public TValue TryGetValue(int key) => (key >= 0 && key < list.Count) ? list[key] : null;
public void Clear()
{
for (var i = 0; i < list.Count; ++i)
list[i] = null;
}
public IEnumerator<TValue> GetEnumerator() => list.Where(v => v != null).GetEnumerator(); // Linq
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public int FirstKeyOf(TValue val) => list.IndexOf(val);
public IDictionary<int, TValue> ToDictionary()
{
var retColl = new SortedList<int, TValue>(list.Count);
for (var i = 0; i < list.Count; ++i)
{
var val = list[i];
if (val != null)
retColl.Add(i, val);
}
return retColl;
}
// and so on...
}
Not thread-safe, obviously.
Be aware, the same value can be present several times in the collection, but with different keys.
I have the below code and now I want to add an UpdateSetting method.
The best way of doing this that I can see is via TryUpdate on the ConcurrentDictionary but that means knowing the previous value so that would require a call to GetSetting which seems a bit yucky. What are your thoughts? Is there a better way?
NOTE: If the value is not in the cache it should do nothing. On successful updating of cache it should call the settingRepository.Update
Thanks
public class MySettings : IMySettings
{
private readonly ISettingRepository settingRepository;
private readonly ConcurrentDictionary<string, object> cachedValues = new ConcurrentDictionary<string, object>();
public MySettings(ISettingRepository settingRepository)
{
this.settingRepository = settingRepository;
}
public string GetSetting(string key)
{
return this.GetSetting<string>(key);
}
public T GetSetting<T>(string key)
{
object value;
if (!this.cachedValues.TryGetValue(key, out value))
{
value = this.GetValueFromRepository(key, typeof(T));
this.cachedValues.TryAdd(key, value);
}
return (T)value;
}
private object GetValueFromRepository(string key, Type type)
{
var stringValue = this.settingRepository.GetSetting(key);
if (stringValue == null)
{
throw new MissingSettingException(string.Format("A setting with the key '{0}' does not exist.", key));
}
if (type == typeof(string))
{
return stringValue;
}
return ConvertValue(stringValue, type);
}
private static object ConvertValue(string stringValue, Type type)
{
return TypeDescriptor.GetConverter(type).ConvertFromString(stringValue);
}
}
Might be worth getting the existing value to possible avoid updating the repository. And an exception if more expensive than a try
public bool UpdateSetting<T>(string key, T value)
{
lock
{
T oldValue;
if (this.cachedValues.TryGetValue(key, out oldValue)
{
if (oldValue != value)
{
this.cachedValues[key] = value;
settingRepository.Update(key, value);
}
return true;
}
else
{
return false;
}
}
}
One way would be to simply set the value, and catch the exception that it will throw if the key is not in the collection.
public bool UpdateSetting<T>(string key, T value)
{
try {
this.cachedValues[key] = value;
} catch (KeyNotFoundException ex) {
return false;
}
return true;
}
Whether this is how you want to handle the key not existing is up to you. But if you decide you want to add the key, then you should use the AddOrUpdate method rather than the simple assignment above. And you won't need to catch that exception in that case.
To address the bigger issue of your backing repository, I think you'll need something along the lines of this.
public bool UpdateSetting<T>(string key, T value)
{
lock {
try {
this.cachedValues[key] = value;
this.settingRepository.Update(... //you'll have to write this
} catch (KeyNotFoundException ex) {
return false;
}
return true;
}
}
I don't think you can avoid the use of a lock to ensure the change to the cache matches the repository. For the same reason, I think some of your existing code may need locking as well. Using ConcurrentDictionary only protects you in the operations on the dictionary. But in the larger scope, there is more going on that needs synchronization.
Is there any prior work of adding tasks to the TPL runtime with a varying priority?
If not, generally speaking, how would I implement this?
Ideally I plan on using the producer-consumer pattern to add "todo" work to the TPL. There may be times where I discover that a low priority job needs to be upgraded to a high priority job (relative to the others).
If anyone has some search keywords I should use when searching for this, please mention them, since I haven't yet found code that will do what I need.
So here is a rather naive concurrent implementation around a rather naive priority queue. The idea here is that there is a sorted set that holds onto pairs of both the real item and a priority, but is given a comparer that just compares the priority. The constructor takes a function that computes the priority for a given object.
As for actual implementation, they're not efficiently implemented, I just lock around everything. Creating more efficient implementations would prevent the use of SortedSet as a priority queue, and re-implementing one of those that can be effectively accessed concurrently is not going to be that easy.
In order to change the priority of an item you'll need to remove the item from the set and then add it again, and to find it without iterating the whole set you'd need to know the old priority as well as the new priority.
public class ConcurrentPriorityQueue<T> : IProducerConsumerCollection<T>
{
private object key = new object();
private SortedSet<Tuple<T, int>> set;
private Func<T, int> prioritySelector;
public ConcurrentPriorityQueue(Func<T, int> prioritySelector, IComparer<T> comparer = null)
{
this.prioritySelector = prioritySelector;
set = new SortedSet<Tuple<T, int>>(
new MyComparer<T>(comparer ?? Comparer<T>.Default));
}
private class MyComparer<T> : IComparer<Tuple<T, int>>
{
private IComparer<T> comparer;
public MyComparer(IComparer<T> comparer)
{
this.comparer = comparer;
}
public int Compare(Tuple<T, int> first, Tuple<T, int> second)
{
var returnValue = first.Item2.CompareTo(second.Item2);
if (returnValue == 0)
returnValue = comparer.Compare(first.Item1, second.Item1);
return returnValue;
}
}
public bool TryAdd(T item)
{
lock (key)
{
return set.Add(Tuple.Create(item, prioritySelector(item)));
}
}
public bool TryTake(out T item)
{
lock (key)
{
if (set.Count > 0)
{
var first = set.First();
item = first.Item1;
return set.Remove(first);
}
else
{
item = default(T);
return false;
}
}
}
public bool ChangePriority(T item, int oldPriority, int newPriority)
{
lock (key)
{
if (set.Remove(Tuple.Create(item, oldPriority)))
{
return set.Add(Tuple.Create(item, newPriority));
}
else
return false;
}
}
public bool ChangePriority(T item)
{
lock (key)
{
var result = set.FirstOrDefault(pair => object.Equals(pair.Item1, item));
if (object.Equals(result.Item1, item))
{
return ChangePriority(item, result.Item2, prioritySelector(item));
}
else
{
return false;
}
}
}
public void CopyTo(T[] array, int index)
{
lock (key)
{
foreach (var item in set.Select(pair => pair.Item1))
{
array[index++] = item;
}
}
}
public T[] ToArray()
{
lock (key)
{
return set.Select(pair => pair.Item1).ToArray();
}
}
public IEnumerator<T> GetEnumerator()
{
return ToArray().AsEnumerable().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void CopyTo(Array array, int index)
{
lock (key)
{
foreach (var item in set.Select(pair => pair.Item1))
{
array.SetValue(item, index++);
}
}
}
public int Count
{
get { lock (key) { return set.Count; } }
}
public bool IsSynchronized
{
get { return true; }
}
public object SyncRoot
{
get { return key; }
}
}
Once you have an IProducerConsumerCollection<T> instance, which the above object is, you can use it as the internal backing object of a BlockingCollection<T> in order to have an easier to use user interface.
ParallelExtensionsExtras contains several custom TaskSchedulers that could be helpful either directly or as a base for your own scheduler.
Specifically, there are two schedulers that may be interesting for you:
QueuedTaskScheduler, which allows you to schedule Tasks at different priorities, but doesn't allow changing the priority of enqueued Tasks.
ReprioritizableTaskScheduler, which doesn't have different priorities, but allows you to move a specific Task to the front or to the back of the queue. (Though changing priority is O(n) in the number of currently waiting Tasks, which could be a problem if you had many Tasks at the same time.)
Is there a way to implement a generic implicit or explicit converter for anything to an array of anything, something like this:
public static implicit operator T[](T objToConvert)
{
return new T[] { objToConvert };
}
No. The closest I can think of is an extension method:
public static T[] AsArray<T>(this T instance)
{
return new T[]{instance};
}
Use as:
var myArray = myInstnace.AsArray();
Note that you can omit the type name from the array constructor, which means the syntax is fairly clean, even with a long type name:
ReallyLongAndAwkwardTypeName value;
MethodThatTakesArray(new[] {value});
Operator overloading methods have to live inside the class they are overriding operators for (one side or the other). Since "T" is not defined, I don't see how this can be accomplished.
You can do it using normal method:
public static T[] ToArray<T>(T objToConvert) {
return new T[] { objToConvert };
}
I don't think you can define generics operator. Note, anyway, that the compiler is sufficient cleaver to guess the type of the generic param, so you can use:
var aString="";
var aStringArray=ToArray(aString);
aStringArray is defined as a string array even if you don't specify the generic param.
I was trying to think of situations where you might really use an implicit conversion to array. I started to wonder if many of the situations where you would want to do this could be alleviated by use of the params keyword.
The main situation that I could think of was that you had a single item of something and wanted to pass it to a function that takes an array as a parameter:
static void Main(string[] args)
{
string x = "I'm just a poor variable. Nobody loves me.";
Stickler.IOnlyTakeArrays_Rawr111(x); // won't go in! square peg, round hole, etc.
// *sigh* fine.
Stickler.IOnlyTakeArrays_Rawr111(new[] { x });
}
class Stickler
{
public static void IOnlyTakeArrays_Rawr111(string[] yum)
{
// ...
}
}
Hopefully in this situation the author of the method that you want to call has choosen to use the params keyword to allow you to pass your variable without wrapping it in an array:
class DataConcierge
{
public static T Create<T>(int id)
{
// ...
}
public static void Save<T>(params T[] items)
{
// ...
}
}
static void Main(string[] args)
{
var customer = DataConcierge.Create<Customer>(123);
// ...
DataConcierge.Save(customer); // this works!
//----------------------------------------------------
// or
//----------------------------------------------------
var customers = new Customer[]
{
DataConcierge.Create<Customer>(123),
DataConcierge.Create<Customer>(234),
DataConcierge.Create<Customer>(345),
};
// ...
DataConcierge.Save(customers); // this works too!
}
Of course, this doesn't really help you in situations where you need convert a variable to a single item array but not as a parameter to a method or in situations where the author of the method didn't use the params keyword.
But what kind of situation would the former be? Assigning an array to a property? Psh. How often does that happen?
And the latter? If the author didn't use the params keyword when they could have, then send them an email complaining about it. If the author is yourself, feel free to be extra belligerent in the email.
Hopefully you can tell that I'm being facetious. Seriously, though, are there any other common usage situations that you can think of where the params keyword would not be applicable?
** Disclaimer: I don't advocate excessive use of the params keyword. Use it if you think you should, but don't take my post to mean that you should always use the params keyword whenever you can.
In the past I've used the concept of a "Conductor" (my own name for it), which is just a class/struct that provides access to an underlying value.
The concept is useful for abstracting the access to a particular value retrieved from somewhere. For example, if you wanted to abstract access to a particular value in a dictionary, you could create a Conductor object that held a reference to the dictionary and the appropriate key for that value. You can also use this concept to easily implement rollback for serializable classes or for value types, though for that you'd need to add Rollback and Commit methods to the Conductor class/struct.
Below is an example of how you can use implicit conversions from T to Conductor and from Conductor to T[] in order to (sort of) achieve what you want.
static void Main(string[] args)
{
// implicit conversion here from Customer to Conductor<Customer>
Conductor<Customer> conductor = DataConcierge.Create<Customer>(123);
if (conductor.HasValue)
{
Console.WriteLine("I got a customer with Id {0}!", conductor.Value.Id);
// implicit conversion here from Conductor<Customer> to Customer[]
DataConcierge.Save<Customer>(conductor);
}
}
public struct Conductor<T> : IConductor<T>, IEquatable<T>, IEquatable<Conductor<T>>, IEquatable<IConductor<T>>
{
private T _Value;
public Conductor(T value)
{
this._Value = value;
}
public T Value
{
get { return this._Value; }
set { this._Value = value; }
}
public bool HasValue
{
get { return this._Value != null; }
}
public T GetValueOrDefault()
{
if (this.HasValue)
return this.Value;
else
return default(T);
}
public T GetValueOrDefault(T #default)
{
if (this.HasValue)
return this.Value;
else
return #default;
}
public bool TryGetValue(out T value)
{
if (this.HasValue)
{
value = this.Value;
return true;
}
else
{
value = default(T);
return false;
}
}
public T[] AsArray()
{
return new T[] { this._Value };
}
public static implicit operator Conductor<T>(T value)
{
return new Conductor<T>(value);
}
public static implicit operator T(Conductor<T> conductor)
{
return conductor.Value;
}
public static implicit operator T[](Conductor<T> conductor)
{
return conductor.AsArray();
}
public bool Equals(T other)
{
var otherEquatable = other as IEquatable<T>;
if (otherEquatable != null)
return otherEquatable.Equals(this.Value);
else
return object.Equals(this.Value, other);
}
public bool Equals(Conductor<T> other)
{
if (other.HasValue)
return this.Equals(other.Value);
else
return !this.HasValue;
}
public bool Equals(IConductor<T> other)
{
if (other != null && other.HasValue)
return this.Equals(other.Value);
else
return !this.HasValue;
}
public override bool Equals(object obj)
{
if (obj == null)
return !this.HasValue;
var conductor = obj as IConductor<T>;
if (conductor != null)
{
if (conductor.HasValue)
return this.Equals(conductor.Value);
else
return !this.HasValue;
}
return object.Equals(this.Value, obj);
}
public override int GetHashCode()
{
if (this.HasValue)
return this.Value.GetHashCode();
else
return 0;
}
public override string ToString()
{
if (this.HasValue)
return this.Value.ToString();
else
return null;
}
}
When i do val = dict["nonexistent key"] i get System.Collections.Generic.KeyNotFoundException
Is there a way i have my dictionary call a member function with the key as a param to generate a value?
-edit-
Maybe i should of been more specific. I want to AUTOMATICALLY call a member function to do what it needs create the proper value for that key. In this case it makes an entry in my DB then gives me back its unique handle. I'll post below what my solution was.
Use an extension method:
static class DictionaryExtensions {
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey,TValue> dic, TKey key, Func<TKey, TValue> valueGenerator) {
TValue val;
if (dic.TryGetValue(key, out val))
return val;
return valueGenerator(key);
}
}
You can call it with:
dic.GetValueOrDefault("nonexistent key", key => "null");
Or pass a member function:
dic.GetValueOrDefault("nonexistent key", MyMemberFunction);
Object value;
if(dict.TryGetValue("nonexistent key", out value))
{
// this only works when key is found..
}
// no exception is thrown here..
Just as an aside, the technique you're talking about is called Memoization
TryGetValue() is good. You can also use ContainsKey() if you aren't performance constrained or don't need the value.
if(myDictionary.ContainsKey("TestKey")
{
System.Print(myDictionary["TestKey"]);
}
string Q = "nonexistent key";
string A = "";
if(dict.containskey(Q))
{
A= dict[Q];
}
else
{
//handler code here
}
public class MyDictionary<K, V>
{
Dictionary<K, V> o = new Dictionary<K, V>();
public delegate V NonExistentKey(K k);
NonExistentKey nonExistentKey;
public MyDictionary(NonExistentKey nonExistentKey_)
{ o = new Dictionary<K, V>();
nonExistentKey = nonExistentKey_;
}
public V this[K k]
{
get {
V v;
if (!o.TryGetValue(k, out v))
{
v = nonExistentKey(k);
o[k] = v;
}
return v;
}
set {o[k] = value;}
}
}