C# dictionaries ValueOrNull / ValueorDefault - c#

Currently I'm using
var x = dict.ContainsKey(key) ? dict[key] : defaultValue
I'd like some way to have dictionary[key] return null for nonexistant keys, so I could write something like
var x = dict[key] ?? defaultValue;
this also winds up being part of linq queries etc. so I'd prefer one-line solutions.

With an extension method:
public static class MyHelper
{
public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dic,
K key,
V defaultVal = default(V))
{
V ret;
bool found = dic.TryGetValue(key, out ret);
if (found) { return ret; }
return defaultVal;
}
void Example()
{
var dict = new Dictionary<int, string>();
dict.GetValueOrDefault(42, "default");
}
}

You can use a helper method:
public abstract class MyHelper {
public static V GetValueOrDefault<K,V>( Dictionary<K,V> dic, K key ) {
V ret;
bool found = dic.TryGetValue( key, out ret );
if ( found ) { return ret; }
return default(V);
}
}
var x = MyHelper.GetValueOrDefault( dic, key );

Here is the "ultimate" solution, in that it is implemented as an extension method, uses the IDictionary interface, provides an optional default value, and is written concisely.
public static TV GetValueOrDefault<TK, TV>(this IDictionary<TK, TV> dic, TK key,
TV defaultVal=default(TV))
{
TV val;
return dic.TryGetValue(key, out val)
? val
: defaultVal;
}

Isn't simply TryGetValue(key, out value) what you are looking for? Quoting MSDN:
When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized.
from http://msdn.microsoft.com/en-us/library/bb347013(v=vs.90).aspx

Related

Get Key and Value types from dictionary in generic method

Id like to be able to work with Dictionaries in generic methods. What Im looking for is a way to get the Type from Key and Value of the dictionary sent to the generic extension method LoadProperty.
This is what I've done so far.
I call the method as an extension
entityObject.LoadProperty<Dictionary<string, int>>("CartonThreshold")
//entityObject.LoadProperty<Dictionary<string, double>>("CartonThreshold")
// ...
public static T LoadProperty<T>(this EntityObject entity, string name) where T : new()
{
EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));
// If request dictionary
if (typeof(T).GetInterface(typeof(IDictionary<,>).Name) != null || typeof(T).Name.Contains("IDictionary"))
{
var dictionaryInstance = (IDictionary)new T();
// Just for testing
var a = dictionaryInstance.Keys.GetType().Name;
var b = dictionaryInstance.Values.GetType().Name;
var key = (T) Convert.ChangeType(prop.Name, typeof (T));
var value = (T) Convert.ChangeType(prop.Value, typeof (T));
dictionaryInstance.Add(key, value);
return (T) dictionaryInstance;
}
// default
return (T)Convert.ChangeType(prop.Value, typeof(T));
}
The goal is to return a correctly typed dictionary
What I was looking for was the GetGenericArguments() extension of GetType()
The method below will return what I need.
public static T LoadProperty<T>(this EntityObject entity, string name) where T : new()
{
EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));
try
{
// If request dictionary
if (typeof(T).GetInterface(typeof(IDictionary<,>).Name) != null || typeof(T).Name.Contains("IDictionary"))
{
var dictionaryInstance = (IDictionary)new T();
var typing = dictionaryInstance.GetType().GetGenericArguments();
Type keyType = typing[0];
Type valueType = typing[1];
// dictionary fallback, set to default of the valuetype if null
object value = prop.Value != null ? Convert.ChangeType(prop.Value, valueType) : Activator.CreateInstance(valueType);
var key = Convert.ChangeType(prop.Name, keyType);
dictionaryInstance.Add(key, value);
return (T)dictionaryInstance;
}
if (prop.Value != null)
{
// default
return (T)Convert.ChangeType(prop.Value, typeof(T));
}
}
catch { }
return default(T);
}
This way I can call the method like this
// Will return a typed dictionary with the EntityObjectProperty name as key and the EntityObjectProperty Value as value
entityObject.LoadProperty<Dictionary<string, int>>("CartonThreshold")
// Will return a string of the EntityObjectProperty Value
entityObject.LoadProperty<string>("CartonThreshold")
// Will return an Int of the EntityObjectProperty Value
entityObject.LoadProperty<int>("CartonThreshold")
Why don't you just define your method like this:
public static IDictionary<K, V> LoadProperty<K, V>(this EntityObject entity, string name)
To get it working with almost anything, you could pass a function to create whatever return type you want:
public static T LoadProperty<TKey,TValue,T>(this EntityObject entity, string name, Func<TKey,TValue,T> createWhatever)
{
EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));
return createWhatever((TKey)prop.Name, (TValue)prop.Value);
}
This would be a bit more verbose at the calling, though.
If I understood your question correctly, what you would like to do is define your method like this:
public static T LoadProperty<T,TKey,TValue>(this EntityObject entity, string name)
where T : IDictionary<TKey,TValue>, new() {
EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));
T t = new T();
t.Add((TKey)prop.Name, TValue(prop.Value));
return t;
}
Then call it with
Dictionary<string,int> property = entityObject.LoadProperty<Dictionary<string,int>, string, int>("test");
The bad thing is that you have to specify all the generic parameters each time...
If it's ok for your concrete case, it would be much simpler like this:
public static IDictionary<TKey,TValue> LoadProperty<TKey,TValue>(this EntityObject entity, string name) {
EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));
var dict = new Dictionary<TKey,TValue>();
dict.Add((TKey)prop.Name, TValue(prop.Value));
return dict;
}
EDIT: after your clarification, what about telling the two cases apart by the number of generic arguments?
public static IDictionary<TKey,TValue> LoadProperty<TKey,TValue>(this EntityObject entity, string name) {
var d = new Dictionary<TKey,TValue>();
// add value from EntityObject
return t;
}
public static TValue LoadProperty<TValue>(this EntityObject entity, string name) {
TValue ret;
// get value from EntityObject
return ret;
}

Why doesn't Dictionary<TKey, TValue> support null key? [duplicate]

This question already has answers here:
Why can't you use null as a key for a Dictionary<bool?, string>?
(11 answers)
Need an IDictionary<TKey,TValue> implementation that will allow a null key
(8 answers)
Closed last year.
Firstly, why doesn't Dictionary<TKey, TValue> support a single null key?
Secondly, is there an existing dictionary-like collection that does?
I want to store an "empty" or "missing" or "default" System.Type, thought null would work well for this.
More specifically, I've written this class:
class Switch
{
private Dictionary<Type, Action<object>> _dict;
public Switch(params KeyValuePair<Type, Action<object>>[] cases)
{
_dict = new Dictionary<Type, Action<object>>(cases.Length);
foreach (var entry in cases)
_dict.Add(entry.Key, entry.Value);
}
public void Execute(object obj)
{
var type = obj.GetType();
if (_dict.ContainsKey(type))
_dict[type](obj);
}
public static void Execute(object obj, params KeyValuePair<Type, Action<object>>[] cases)
{
var type = obj.GetType();
foreach (var entry in cases)
{
if (entry.Key == null || type.IsAssignableFrom(entry.Key))
{
entry.Value(obj);
break;
}
}
}
public static KeyValuePair<Type, Action<object>> Case<T>(Action action)
{
return new KeyValuePair<Type, Action<object>>(typeof(T), x => action());
}
public static KeyValuePair<Type, Action<object>> Case<T>(Action<T> action)
{
return new KeyValuePair<Type, Action<object>>(typeof(T), x => action((T)x));
}
public static KeyValuePair<Type, Action<object>> Default(Action action)
{
return new KeyValuePair<Type, Action<object>>(null, x => action());
}
}
For switching on types. There are two ways to use it:
Statically. Just call Switch.Execute(yourObject, Switch.Case<YourType>(x => x.Action()))
Precompiled. Create a switch, and then use it later with switchInstance.Execute(yourObject)
Works great except when you try to add a default case to the "precompiled" version (null argument exception).
Why:
As described before, the problem is that Dictionary requires an implementation of the Object.GetHashCode() method. null does not have an implementation, therefore no hash code associated.
Solution: I have used a solution similar to a NullObject pattern using generics that enables you to use the dictionary seamlessly (no need for a different dictionary implementation).
You can use it like this:
var dict = new Dictionary<NullObject<Type>, string>();
dict[typeof(int)] = "int type";
dict[typeof(string)] = "string type";
dict[null] = "null type";
Assert.AreEqual("int type", dict[typeof(int)]);
Assert.AreEqual("string type", dict[typeof(string)]);
Assert.AreEqual("null type", dict[null]);
You just need to create this struct once in a lifetime :
public struct NullObject<T>
{
[DefaultValue(true)]
private bool isnull;// default property initializers are not supported for structs
private NullObject(T item, bool isnull) : this()
{
this.isnull = isnull;
this.Item = item;
}
public NullObject(T item) : this(item, item == null)
{
}
public static NullObject<T> Null()
{
return new NullObject<T>();
}
public T Item { get; private set; }
public bool IsNull()
{
return this.isnull;
}
public static implicit operator T(NullObject<T> nullObject)
{
return nullObject.Item;
}
public static implicit operator NullObject<T>(T item)
{
return new NullObject<T>(item);
}
public override string ToString()
{
return (Item != null) ? Item.ToString() : "NULL";
}
public override bool Equals(object obj)
{
if (obj == null)
return this.IsNull();
if (!(obj is NullObject<T>))
return false;
var no = (NullObject<T>)obj;
if (this.IsNull())
return no.IsNull();
if (no.IsNull())
return false;
return this.Item.Equals(no.Item);
}
public override int GetHashCode()
{
if (this.isnull)
return 0;
var result = Item.GetHashCode();
if (result >= 0)
result++;
return result;
}
}
It doesn't support it because the dictionary hashes the key to determine the index, which it can't do on a null value.
A quick fix would be to create a dummy class, and insert the key value ?? dummyClassInstance.
Would need more information about what you're actually trying to do to give a less 'hacky' fix
It just hit me that your best answer is probably to just keep track of whether a default case has been defined:
class Switch
{
private Dictionary<Type, Action<object>> _dict;
private Action<object> defaultCase;
public Switch(params KeyValuePair<Type, Action<object>>[] cases)
{
_dict = new Dictionary<Type, Action<object>>(cases.Length);
foreach (var entry in cases)
if (entry.Key == null)
defaultCase = entry.Value;
else
_dict.Add(entry.Key, entry.Value);
}
public void Execute(object obj)
{
var type = obj.GetType();
if (_dict.ContainsKey(type))
_dict[type](obj);
else if (defaultCase != null)
defaultCase(obj);
}
...
The whole rest of your class would remain untouched.
NameValueCollection could take null key.
If you really want a dictionary that allows null keys, here's my quick implementation (not well-written or well-tested):
class NullableDict<K, V> : IDictionary<K, V>
{
Dictionary<K, V> dict = new Dictionary<K, V>();
V nullValue = default(V);
bool hasNull = false;
public NullableDict()
{
}
public void Add(K key, V value)
{
if (key == null)
if (hasNull)
throw new ArgumentException("Duplicate key");
else
{
nullValue = value;
hasNull = true;
}
else
dict.Add(key, value);
}
public bool ContainsKey(K key)
{
if (key == null)
return hasNull;
return dict.ContainsKey(key);
}
public ICollection<K> Keys
{
get
{
if (!hasNull)
return dict.Keys;
List<K> keys = dict.Keys.ToList();
keys.Add(default(K));
return new ReadOnlyCollection<K>(keys);
}
}
public bool Remove(K key)
{
if (key != null)
return dict.Remove(key);
bool oldHasNull = hasNull;
hasNull = false;
return oldHasNull;
}
public bool TryGetValue(K key, out V value)
{
if (key != null)
return dict.TryGetValue(key, out value);
value = hasNull ? nullValue : default(V);
return hasNull;
}
public ICollection<V> Values
{
get
{
if (!hasNull)
return dict.Values;
List<V> values = dict.Values.ToList();
values.Add(nullValue);
return new ReadOnlyCollection<V>(values);
}
}
public V this[K key]
{
get
{
if (key == null)
if (hasNull)
return nullValue;
else
throw new KeyNotFoundException();
else
return dict[key];
}
set
{
if (key == null)
{
nullValue = value;
hasNull = true;
}
else
dict[key] = value;
}
}
public void Add(KeyValuePair<K, V> item)
{
Add(item.Key, item.Value);
}
public void Clear()
{
hasNull = false;
dict.Clear();
}
public bool Contains(KeyValuePair<K, V> item)
{
if (item.Key != null)
return ((ICollection<KeyValuePair<K, V>>)dict).Contains(item);
if (hasNull)
return EqualityComparer<V>.Default.Equals(nullValue, item.Value);
return false;
}
public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<K, V>>)dict).CopyTo(array, arrayIndex);
if (hasNull)
array[arrayIndex + dict.Count] = new KeyValuePair<K, V>(default(K), nullValue);
}
public int Count
{
get { return dict.Count + (hasNull ? 1 : 0); }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(KeyValuePair<K, V> item)
{
V value;
if (TryGetValue(item.Key, out value) && EqualityComparer<V>.Default.Equals(item.Value, value))
return Remove(item.Key);
return false;
}
public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
{
if (!hasNull)
return dict.GetEnumerator();
else
return GetEnumeratorWithNull();
}
private IEnumerator<KeyValuePair<K, V>> GetEnumeratorWithNull()
{
yield return new KeyValuePair<K, V>(default(K), nullValue);
foreach (var kv in dict)
yield return kv;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
NHibernate comes with a NullableDictionary. That did it for me.
https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Util/NullableDictionary.cs
Dictionary will hash the key supplie to get the index , in case of null , hash function can not return a valid value that's why it does not support null in key.
In your case you are trying to use null as a sentinel value (a "default") instead of actually needing to store null as a value. Rather than go to the hassle of creating a dictionary that can accept null keys, why not just create your own sentinel value. This is a variation on the "null object pattern":
class Switch
{
private class DefaultClass { }
....
public void Execute(object obj)
{
var type = obj.GetType();
Action<object> value;
// first look for actual type
if (_dict.TryGetValue(type, out value) ||
// look for default
_dict.TryGetValue(typeof(DefaultClass), out value))
value(obj);
}
public static void Execute(object obj, params KeyValuePair<Type, Action<object>>[] cases)
{
var type = obj.GetType();
foreach (var entry in cases)
{
if (entry.Key == typeof(DefaultClass) || type.IsAssignableFrom(entry.Key))
{
entry.Value(obj);
break;
}
}
}
...
public static KeyValuePair<Type, Action<object>> Default(Action action)
{
return new KeyValuePair<Type, Action<object>>(new DefaultClass(), x => action());
}
}
Note that your first Execute function differs significantly from your second. It may be the case that you want something like this:
public void Execute(object obj)
{
Execute(obj, (IEnumerable<KeyValuePair<Type, Action<object>>>)_dict);
}
public static void Execute(object obj, params KeyValuePair<Type, Action<object>>[] cases)
{
Execute(obj, (IEnumerable<KeyValuePair<Type, Action<object>>>)cases);
}
public static void Execute(object obj, IEnumerable<KeyValuePair<Type, Action<object>>> cases)
{
var type = obj.GetType();
Action<object> defaultEntry = null;
foreach (var entry in cases)
{
if (entry.Key == typeof(DefaultClass))
defaultEntry = entry.Value;
if (type.IsAssignableFrom(entry.Key))
{
entry.Value(obj);
return;
}
}
if (defaultEntry != null)
defaultEntry(obj);
}
I come across this thread some days ago and needed a well thought out and clever solution to handle null keys. I took the time and implemented one by me to handle more scenarios.
You can find my implementation of NullableKeyDictionary currently in my pre-release package Teronis.NetStandard.Collections (0.1.7-alpha.37).
Implementation
public class NullableKeyDictionary<KeyType, ValueType> : INullableKeyDictionary<KeyType, ValueType>, IReadOnlyNullableKeyDictionary<KeyType, ValueType>, IReadOnlyCollection<KeyValuePair<INullableKey<KeyType>, ValueType>> where KeyType : notnull
public interface INullableKeyDictionary<KeyType, ValueType> : IDictionary<KeyType, ValueType>, IDictionary<NullableKey<KeyType>, ValueType> where KeyType : notnull
public interface IReadOnlyNullableKeyDictionary<KeyType, ValueType> : IReadOnlyDictionary<KeyType, ValueType>, IReadOnlyDictionary<NullableKey<KeyType>, ValueType> where KeyType : notnull
Usage (Excerpt of the Xunit test)
// Assign.
var dictionary = new NullableKeyDictionary<string, string>();
IDictionary<string, string> nonNullableDictionary = dictionary;
INullableKeyDictionary<string, string> nullableDictionary = dictionary;
// Assert.
dictionary.Add("value");
/// Assert.Empty does cast to IEnumerable, but our implementation of IEnumerable
/// returns an enumerator of type <see cref="KeyValuePair{NullableKey, TValue}"/>.
/// So we test on correct enumerator implementation wether it can move or not.
Assert.False(nonNullableDictionary.GetEnumerator().MoveNext());
Assert.NotEmpty(nullableDictionary);
Assert.Throws<ArgumentException>(() => dictionary.Add("value"));
Assert.True(dictionary.Remove());
Assert.Empty(nullableDictionary);
dictionary.Add("key", "value");
Assert.True(nonNullableDictionary.GetEnumerator().MoveNext());
Assert.NotEmpty(nullableDictionary);
Assert.Throws<ArgumentException>(() => dictionary.Add("key", "value"));
dictionary.Add("value");
Assert.Equal(1, nonNullableDictionary.Count);
Assert.Equal(2, nullableDictionary.Count);
The following overloads exists for Add(..):
void Add([AllowNull] KeyType key, ValueType value)
void Add(NullableKey<KeyType> key, [AllowNull] ValueType value)
void Add([AllowNull] ValueType value); // Shortcut for adding value with null key.
This class should behave same and intuitive as the dictionary does.
For Remove(..) keys you can use the following overloads:
void Remove([AllowNull] KeyType key)
void Remove(NullableKey<KeyType> key)
void Remove(); // Shortcut for removing value with null key.
The indexers do accept [AllowNull] KeyType or NullableKey<KeyType>. So supported scenarios, like they are stated in other posts, are supported:
var dict = new NullableKeyDictionary<Type, string>
dict[typeof(int)] = "int type";
dict[typeof(string)] = "string type";
dict[null] = "null type";
// Or:
dict[NullableKey<Type>.Null] = "null type";
I highly appreciate feedback and suggestions for improvements. :)
EDIT: Real answer to the question actually being asked: Why can't you use null as a key for a Dictionary<bool?, string>?
The reason the generic dictionary doesn't support null is because TKey might be a value type, which doesn't have null.
new Dictionary<int, string>[null] = "Null"; //error!
To get one that does, you could either use the non-generic Hashtable (which uses object keys and values), or roll your own with DictionaryBase.
Edit: just to clarify why null is illegal in this case, consider this generic method:
bool IsNull<T> (T value) {
return value == null;
}
But what happens when you call IsNull<int>(null)?
Argument '1': cannot convert from '<null>' to 'int'
You get a compiler error, since you can't convert null to an int. We can fix it, by saying that we only want nullable types:
bool IsNull<T> (T value) where T : class {
return value == null;
}
And, that's A-Okay. The restriction is that we can no longer call IsNull<int>, since int is not a class (nullable object)

Two-value dictionary which returns any of the value for a specific key

I need to create a dictionary that has 2 values per key, and it must return one of the 2 values with the same probability.
Example:
myDicry
{
key = "A", value1=15, value2=56;
}
int firstCall = myDicry["A"]; // = 15
int secondCall = myDicry["A"]; // = 56
It would be possible to write an IDictionary<TKey, TValue> implementation that behaved in this manner, but that would not be a good idea: most people would find a non-deterministic indexer for a collection-class very unintuitive.
Instead, I suggest you make this the responsibility of the value for a key, rather than the Dictionary itself. One option would be to write a custom-type that is capable of picking from a set of possibilities with equal probability. For example:
public class UnbiasedRandomPicker<T>
{
private readonly Random _rand = new Random();
private readonly T[] _possibilities;
public UnbiasedRandomPicker(params T[] possibilities)
{
// argument validation omitted
_possibilities = possibilities;
}
public T GetRandomValue()
{
return _possibilities[_rand.Next(_possibilities.Length)];
}
}
You could then use the dictionary like this:
var dict = new Dictionary<string, UnbiasedRandomPicker<int>>
{
{"A", new UnbiasedRandomPicker<int>(15, 56)},
{"B", new UnbiasedRandomPicker<int>(25, 13)}
};
int randomValueFromA = dict["A"].GetRandomValue();
There's nothing built into the framework to do this, but you'd probably want to implement it by creating a "wrapper" type which had a Dictionary<TKey, Tuple<TValue, TValue>>. You'd then write an indexer to choose appropriately between the two values.
I would actually just implement this in a class that uses a Dictionary<TKey, TValue[]> internally. That way you could even implement the type to have a variable number of values per key.
Like:
class RandomDictionary<TKey, TValue>
{
Dictionary<TKey, TValue[]> m_dict;
Random m_random;
public RandomDictionary()
{
m_dict = new Dictionary<TKey, TValue[]>();
m_random = new Random();
}
public TValue this[TKey key]
{
get
{
TValue[] values = m_dict[key];
return values[m_random.Next(0, values.Length)];
}
}
public void Define(TKey key, params TValue[] values)
{
m_dict[key] = new TValue[values.Length];
Array.Copy(values, m_dict[key], values.Length);
}
public bool TryGetValue(TKey key, out TValue value)
{
TValue[] values;
if (!m_dict.TryGetValue(key, out values))
{
value = default(TValue);
return false;
}
value = values[m_random.Next(0, values.Length)];
return true;
}
}
Use Tuple as dictionary value type.
IDictionary<string, Tuple<int, int>> doubleDictionary = new Dictionary<string, Tuple<int, int>>();
// ...
int secondValue = doubleDictionary["A"].Item2;
You could also write an extension method for the dictionary, so you could create something like this:
IDictionary<string, Tuple<int, int>> doubleDictionary = new Dictionary<string, Tuple<int, int>>();
doubleDictionary.GetRandomValueForKey("A");
Then you can use this with any dictionary.
public static void GetRandomValueForKey(this Dictionary<string, Tuple<int, int>> dict,
string key)
{
... Code to return the value
}
^^ that was written off the top of my head, so please excuse me if this is slightly wrong.
This below code will solve the dictionary part of the problem and make the randomization customizable so that you can apply a level so pseudo-randomness that suits your needs. (or simply hard code it instead of the use of a functor)
public class DoubleDictionary<K, T> : IEnumerable<KeyValuePair<K, T>>
{
private readonly Dictionary<K, Tuple<T, T>> _dictionary = new Dictionary<K, Tuple<T, T>>();
private readonly Func<bool> _getFirst;
public DoubleDictionary(Func<bool> GetFirst) {
_getFirst = GetFirst;
}
public void Add(K Key, Tuple<T, T> Value) {
_dictionary.Add(Key, Value);
}
public T this[K index] {
get {
Tuple<T, T> pair = _dictionary[index];
return GetValue(pair);
}
}
private T GetValue(Tuple<T, T> Pair) {
return _getFirst() ? Pair.Item1 : Pair.Item2;
}
public IEnumerable<K> Keys {
get {
return _dictionary.Keys;
}
}
public IEnumerable<T> Values {
get {
foreach (var pair in _dictionary.Values) {
yield return GetValue(pair);
}
}
}
IEnumerator<KeyValuePair<K, T>> IEnumerable<KeyValuePair<K, T>>.GetEnumerator() {
foreach (var pair in _dictionary) {
yield return new KeyValuePair<K, T>(pair.Key, GetValue(pair.Value));
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return ((IEnumerable<KeyValuePair<K, T>>)this).GetEnumerator();
}
}

C#: generic math functions (Min, Max etc.)

I was thinking about writing generic functions for basic Math operations such as Min, Max etc.
But i i dont know how to compare two generic types :
public T Max<T>(T v1, T v2) where T: struct
{
return (v1 > v2 ? v1 : v2);
}
How about that?
Thank you.
You probably want to constrain the generic types to implement IComparable:
public T Max<T>(T v1, T v2) where T: struct, IComparable<T>
and then use the CompareTo method:
{
return (v1.CompareTo(v2) > 0 ? v1 : v2);
}
If you only want to create comparison functions then you could use the default comparer for the type T. For example:
public static T Max<T>(T x, T y)
{
return (Comparer<T>.Default.Compare(x, y) > 0) ? x : y;
}
If T implements IComparable<T> then that comparer will be used; if T doesn't implement IComparable<T> but does implement IComparable then that comparer will be used; if T doesn't implement either IComparable<T> or IComparable then a runtime exception will be thrown.
If you want/need to do more than just compare the items then you could have a look at the generic operators implementation in MiscUtil and the related article.
Let me disagree.
The #LukeH's implementation is not Generic.
I will explain why it is not Generic:
Comparer<T>.Default involves inspecting T at run-time to determine if it implements IComparable<T>, IComparable or neither.
Although this behavior is not well documented in http://msdn.microsoft.com/en-us/library/azhsac5f.aspx, we can deduct it because Comparer<T>.Default throws an exception when T does not implement neither. If the inspection was done at compilation-time there would be no need for an exception (runtime), with an compile-time error would suffice.
Then, as Comparer<T>.Default uses Reflection, this means a high cost on Run-Time, then...., It is NOT Generic... Why?
Because Generic Programming means: A single algorithm (Generic) can cover many implementations (for many types) maintaining efficiency of hand-written versions.
Take an example. The handwritten version for integers would be:
public static int Max( int x, int y)
{
return (x.CompareTo(y) > 0) ? x : y;
}
It is very simple, involving only a comparison (or maybe more, depending on how Int32.CompareTo() is implemented).
If we use the #LukeH's implementation, we are adding Reflection to something that is very simple.
In short:
Always prefer Compilation-time errors to Run-Time Exceptions ( this is not Javascript, Ruby,... :-) )
This implementation is less efficient compared to the handwritten version (for any type)
On the other hand.
What do you think Max should return when x and y are equivalents?
I'm starting to analyze Real-Generic implementations....
The ideal implementation would be something like...
public static T Max<T>(T x, T y, Func<T, T, int> cmp)
{
return (cmp(x, y) > 0) ? x : y;
}
//Pseudo-code ( note the 'or' next to 'where' )
public static T Max<T>(T x, T y) where T: IComparable<T> or IComparable
{
return Max(x, y, (a, b) => { return a.CompareTo(b); });
}
This is not possible in C#, the next try is could be...
//pseudo-code
public static T Max<T>(T x, T y, Func<T, T, int> cmp)
{
return (cmp(x, y) > 0) ? x : y;
}
public static T Max<T>(T x, T y) where T: IComparable<T>
{
return Max(x, y, (a, b) => { return a.CompareTo(b); });
}
public static T Max<T>(T x, T y) where T: IComparable
{
return Max(x, y, (a, b) => { return a.CompareTo(b); });
}
But, this is neither possible, because overload resolution doesn't takes into account Generics Constraints....
Then, I'll leave out IComparable consciously. I'm just going to worry about IComparable<T>
public static T Max<T>(T x, T y, Func<T, T, int> cmp)
{
return (cmp(x, y) > 0) ? x : y;
}
public static T Max<T>(T x, T y) where T: IComparable<T>
{
return Max(x, y, (a, b) => { return a.CompareTo(b); });
}
This is a little too late, but why not use dynamic types and delegates as an alternative to IComparable? This way you get compile-type safety in most cases and will only get a runtime error when the types supplied both do not support the operator < and you fail to provide the default comparer as an argument.
public static T Max<T>(T first, T second, Func<T,T,bool> f = null)
{
Func<dynamic,dynamic,bool> is_left_smaller = (x, y) => x < y ? true : false;
var compare = f ?? new Func<T, T, bool>((x, y) => is_left_smaller(x, y));
return compare(first, second) ? second : first;
}
The solution I present on this answer would have worked (I actually did something like this) at the time the question was asked. I'm surprised no answer presents this alternative, thus I'll present it.
You can (and could have used back then) Linq.Expressions (Which was added in .NET 3.5, in 2007, making it a valid answer at the time of the question).
For starters:
using System.Linq.Expressions;
// ...
public T Max<T>(T v1, T v2)
{
var expression = Expression.GreaterThan
(
Expression.Constant(v1),
Expression.Constant(v2)
);
return Expression.Lambda<Func<bool>>(expression).Compile()() ? v1 : v2);
}
That has no need of dynamic, or Comparison<T>/IComparer<T>.
I believe that having a way to specify a custom comparison is better, but that is not what we are doing here. And of course, any type for which the presented solution works, Comparer<T>.Default would work. However, using Linq.Expressions would allow you implement any arithmetic operations. Take this as illustration of that approach.
There is, of course, overhead. Let us have a version that does compile to a function with parameters, we can think later about how to cache it:
using System.Linq.Expressions;
// ...
public T Max<T>(T v1, T v2)
{
var a = Expression.Parameter(typeof(int), "a");
var b = Expression.Parameter(typeof(int), "b");
var lambda = Expression.Lambda<Func<T, T, bool>>
(
Expression.GreaterThan(a, b),
new[]{a, b}
);
return ((Func<T, T, bool>)lambda.Compile())(v1, v2) ? v1 : v2;
}
Alright, to cache it, let us start with the generic class approach, which is easier to write:
using System.Linq.Expressions;
class GenericMath<T>
{
private static Func<T, T, bool>? _greaterThan;
public static Func<T, T, bool> GetGreaterThan()
{
if (_greaterThan == null)
{
var a = Expression.Parameter(typeof(int), "a");
var b = Expression.Parameter(typeof(int), "b");
var lambda = Expression.Lambda<Func<T, T, bool>>
(
Expression.GreaterThan(a, b),
new[]{a, b}
);
_greaterThan = (Func<T, T, bool>)lambda.Compile();
}
return _greaterThan;
}
public static T Max(T v1, T v2)
{
return GetGreaterThan()(v1, v2) ? v1 : v2;
}
}
Of course, statics on generics has drawbacks (there is a performance cost, plus the memory is never released). We can start our way to a better solution by using a dictionary cache instead:
using System.Linq.Expressions;
class GenericMath
{
private readonly static Dictionary<Type, Delegate> _gtCache = new Dictionary<Type, Delegate>();
public static Func<T, T, bool> GetGreaterThan<T>()
{
if (!_gtCache.TryGetValue(typeof(T), out var #delegate) || #delegate == null)
{
var a = Expression.Parameter(typeof(int), "a");
var b = Expression.Parameter(typeof(int), "b");
var lambda = Expression.Lambda<Func<T, T, bool>>
(
Expression.GreaterThan(a, b),
new[]{a, b}
);
#delegate = lambda.Compile();
_addCache[typeof(T)] = #delegate;
}
return (Func<T, T, bool>)#delegate;
}
public static T Max<T>(T v1, T v2)
{
return GetGreaterThan<T>()(v1, v2) ? v1 : v2;
}
}
Ok, I hear you, I have introduced a new problem: that solution is not thread-safe.
We could use ConcurrentDictionary (added in .NET 4.0, which -if I'm not mistaken- was on beta at the time of the question), but we would not be releasing memory anyway. Instead, we can make a custom class for this use:
public sealed class TypeCacheDict<TValue>
{
private const int Capacity = 256;
private readonly Entry[] _entries;
public TypeCacheDict()
{
_entries = new Entry[Capacity];
}
public TValue this[Type key]
{
get
{
if (TryGetValue(key, out var value))
{
return value;
}
throw new KeyNotFoundException();
}
set => Add(key, value);
}
public void Add(Type key, TValue value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
var hash = key.GetHashCode();
var index = hash & (_entries.Length - 1);
var entry = _entries[index];
Thread.MemoryBarrier();
if (entry?.Hash != hash || !entry.Key.Equals(key))
{
Interlocked.Exchange(ref _entries[index], new Entry(hash, key, value));
}
}
public bool TryGetValue(Type key, out TValue value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
var hash = key.GetHashCode();
var index = hash & (_entries.Length - 1);
var entry = _entries[index];
Thread.MemoryBarrier();
if (entry?.Hash == hash && entry.Key.Equals(key))
{
value = entry.Value;
return value != null;
}
value = default;
return false;
}
private sealed class Entry
{
internal readonly int Hash;
internal readonly Type Key;
internal readonly TValue Value;
internal Entry(int hash, Type key, TValue value)
{
Hash = hash;
Key = key;
Value = value;
}
}
}
This TypeCacheDict is thread-safe. First of all Entry is immutable. We don't need to worry about shared access to it. Plus, it a reference type, so replacing it is an atomic operation. We are using Thread.MemoryBarrier and Interlocked.Exchange o mimic Volatile.Read and Volatile.Write because Volatile was not available (and Thread.Volatile* lacks generic overload, and I would rather not instroduce extra casts).
With this new type we can now write:
private readonly static TypeCacheDict<Delegate> _gtCache = new TypeCacheDict<Delegate>();
The rest of the code could be left unchanged. Although there is room for improvement: TryGetOrAdd:
public TValue TryGetOrAdd(Type key, Func<TValue> valueFactory)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (valueFactory == null)
{
throw new ArgumentNullException(nameof(valueFactory));
}
var hash = key.GetHashCode();
var index = hash & (_entries.Length - 1);
var entry = _entries[index];
Thread.MemoryBarrier();
if (entry?.Hash == hash && entry.Key.Equals(key))
{
return entry.Value;
}
var value = valueFactory();
Interlocked.Exchange(ref _entries[index], new Entry(hash, key, value));
return value;
}
Which allows us to write:
public static Func<T, T, bool> GetGreaterThan<T>()
{
return (Func<T, T, bool>)_gtCache.TryGetOrAdd
(
typeof(T),
()=>
{
var a = Expression.Parameter(typeof(int), "a");
var b = Expression.Parameter(typeof(int), "b");
var lambda = Expression.Lambda<Func<T, T, bool>>(Expression.GreaterThan(a, b), new[]{a, b});
return lambda.Compile();
}
);
}
Of course, this is how you use it:
Console.WriteLine(GenericMath.Max<int>(90, 100)); // 100
To demostrate, the power of this approach, this is Add:
private readonly static TypeCacheDict<Delegate> _addCache = new TypeCacheDict<Delegate>();
public static Func<T, T, T> GetAdd<T>()
{
return (Func<T, T, T>)_addCache.TryGetOrAdd
(
typeof(T),
()=>
{
var a = Expression.Parameter(typeof(int), "a");
var b = Expression.Parameter(typeof(int), "b");
var lambda = Expression.Lambda<Func<T, T, T>>(Expression.Add(a,b), new[]{a, b});
return lambda.Compile();
}
);
}
public static T Add<T>(T v1, T v2)
{
return GetAdd<T>()(v1, v2);
}
And this is how you use it:
Console.WriteLine(GenericMath.Add<int>(90, 100)); // 190
.NET 7 introduces a new feature - generic math (read more here and here) which is based on addition of static abstract interface methods. This feature introduces a lot of interfaces which allow to generically abstract over number types and/or math operations, which allows to rewrite the function in question as:
public T Max<T>(T v1, T v2) where T: IComparisonOperators<T, T, bool> => v1 > v2 ? v1 : v2;
Note that for build-in number types usually you don't need to define your own Max because it is already defined on the INumber<T> interface:
public interface INumber<TSelf> :
// ... other interfaces,
System.Numerics.IComparisonOperators<TSelf,TSelf,bool>
// ... other interfaces
where TSelf : INumber<TSelf>
From memory, T also needs to be IComparable (add that to the where), and then you use v1.CompareTo(v2) > 0 etc.
Necromancing.
You can have a Max/Min function on an arbitrary number of parameters:
public static T Min<T>(params T[] source)
where T: struct, IComparable<T>
{
if (source == null)
throw new System.ArgumentNullException("source");
T value = default(T);
bool hasValue = false;
foreach (T x in source)
{
if (hasValue)
{
// if (x < value) // https://learn.microsoft.com/en-us/dotnet/api/system.icomparable-1?view=netcore-3.1
// Less than zero This object precedes the object specified by the CompareTo method in the sort order.
// Zero This current instance occurs in the same position in the sort order as the object specified by the CompareTo method argument.
// Greater than zero
if (x.CompareTo(value) < 0)
value = x;
}
else
{
value = x;
hasValue = true;
}
}
if (hasValue)
return value;
throw new System.InvalidOperationException("Sequence contains no elements");
}
public static T Max<T>(params T[] source)
where T : struct, IComparable<T>
{
if (source == null)
throw new System.ArgumentNullException("source");
T value = default(T);
bool hasValue = false;
foreach (T x in source)
{
if (hasValue)
{
// if (x > value) // https://learn.microsoft.com/en-us/dotnet/api/system.icomparable-1?view=netcore-3.1
// Less than zero This object precedes the object specified by the CompareTo method in the sort order.
// Zero This current instance occurs in the same position in the sort order as the object specified by the CompareTo method argument.
// Greater than zero
if (x.CompareTo(value) > 0)
value = x;
}
else
{
value = x;
hasValue = true;
}
}
if (hasValue)
return value;
throw new System.InvalidOperationException("Sequence contains no elements");
}

C# dictionary<> missing key

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

Categories

Resources