Faithium
Faithium

Reputation: 131

Equivalent of java.lang.Number in C#

I want to make arithmetic operations between dictionaries with numbers as value. This is my code:

public class DictionaryOperation {

    public static Dictionary<TKey, double> Add<TKey>(Dictionary<TKey, double> d1, Dictionary<TKey, double> d2) {
        Dictionary<TKey, double> result = new Dictionary<TKey, double>();
        foreach (TKey key in d1.Keys) {
            if (d2.ContainsKey(key))
                result[key] = d1[key] + d2[key];
            else
                result[key] = d1[key];
        }
        foreach (TKey key in d2.Keys) {
            if (!result.ContainsKey(key))
                result[key] = d2[key];
        }
        return result;
    }
}

I would like to know if I can create only one method for any numeric type (int float, decimal, ...) or do I have to create one method per numeric type, which means there will be the same code in each methods.

I want to be able to do this:

Dictionary<string, int> ints = DictionaryOperation.Add(new Dictionary<string, int>(), new Dictionary<string, int>());
Dictionary<string, float> floats = DictionaryOperation.Add(new Dictionary<string, float>(), new Dictionary<string, float>());

Upvotes: 2

Views: 382

Answers (1)

Philipp Grathwohl
Philipp Grathwohl

Reputation: 2836

You can avoid writing the same Method for every numeric type by using generics. You already have a generic key in your dictionary. The only thing missing is the generic value. Change your method to use a generic dictionary value:

public static Dictionary<TKey, TValue> Add<TKey, TValue>(Dictionary<TKey, TValue> d1, Dictionary<TKey, TValue> d2) 
    where TValue : IComparable

The problem is, that there is no type constraint that allows only numbers (or objects that can be added with the + operator). I used IComparable in the line above because all numeric types are comparable.

The next problem is, the IComparable does not help when trying to use the + operator. For this you can use dynamics like so:

dynamic a = d1[key];
dynamic b = d2[key];
result[key] = a + b;

Now you can use the method for all types that implement IComparable. BUT you have no compile time safety. That means you will get runtime errors for all types that do not implement the + operator.

This problem is already described here: C# Adding two Generic Values

Here the full method:

public static Dictionary<TKey, TValue> Add<TKey, TValue>(Dictionary<TKey, TValue> d1, Dictionary<TKey, TValue> d2) 
        where TValue : IComparable
    {
        Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();
    foreach (TKey key in d1.Keys) {
        if (d2.ContainsKey(key))
        {
            dynamic a = d1[key];
            dynamic b = d2[key];
            result[key] = a + b;
        }
        else
            result[key] = d1[key];
    }
    foreach (TKey key in d2.Keys) {
        if (!result.ContainsKey(key))
            result[key] = d2[key];
    }
    return result;
}

Upvotes: 2

Related Questions