Home > Software design >  How to make a method generic in c#?
How to make a method generic in c#?

Time:03-22

I have couple of methods and it keeps on expanding. So, I am planning to make it generic. Can anyone please help me with that. Atleast the method definition.

private static Dictionary<string, class1> PToDictionary(MapField<string, class1Proto> keyValuePairs)
{
    Dictionary<string, class1> keyValues = new();
    foreach (var pair in keyValuePairs)
    {
       **keyValues[pair.Key] = pToR(pair.Value);**
    }
    return keyValues;
}

My another method is :

private static Dictionary<Uri, class2> PToDictionary1(MapField<string, class2Proto> keyValuePairs)
{
        Dictionary<string, class2> keyValues = new();
        foreach (var pair in keyValuePairs)
        {
           **keyValues[new Uri(pair.Key)] = pToR1(pair.Value);**
        }
        return keyValues;
}

How can I make this generic so that when more methods are added, I dont need to add code. I was thinking something like this, but errors are :

//   Not sure how to call this method after Func is there
    private static Dictionary<TKey, TValue> PToDictionary<TKey, TValue, TKeyProto, TValueProto>(MapField<TKeyProto, TValueProto> keyValuePairs, Func<TKeyProto, TKey> keyFunc, Func<TValueProto, TValue> valueFunc)
{
   //How can I generalize my above method ?
}

Can someone help me complete the method ?

CodePudding user response:

You don't need an extra method at all. LINQ already provides everything you need, combined with the fact that MapField implements IDictionary<TKey, TValue> (and therefore IEnumerable<KeyValuePair<TKey, TValue>>.

You'd just call:

var dictionary = repeatedField.ToDictionary(
    pair => ConvertKey(pair.Key), pair => ConvertValue(pair.Value));

(where ConvertKey would be whatever code you want to convert the repeated field key into the dictionary key, and likewise for ConvertValue).

Sample calls:

var d1 = repeatedField1.ToDictionary(pair => pair.Key, pair => pToR(pair.Value));

var d2 = repeatedField2.ToDictionary(
    pair => new Uri(pair.Key), pair => pToR1(pair.Value));

... but you may be able to remove the pToR and pToR1 methods anyway. (It's hard to tell without information about what they're doing...)

CodePudding user response:

You can use the following method to convert MapField<TKeyProto, TValueProto> to Dictionary<TKey, TValue>:

public static Dictionary<TKey, TValue> PToDictionary<TKey, TValue, TKeyProto, TValueProto>(
    MapField<TKeyProto, TValueProto> keyValuePairs,
    Func<TKeyProto, TKey> mapKey,
    Func<TValueProto, TValue> mapValue
)
{
    Dictionary<TKey, TValue> keyValues = new();
    foreach (var pair in keyValuePairs)
    {
        keyValues[mapKey(pair.Key)] = mapValue(pair.Value);
    }
    return keyValues;
}

Here, mapKey is a function that converts MapField's key to a dictionary key. Similarly, mapValue converts MapField's value to a dictionary value.

Another way is to make usage of LINQ ToDictionary extension method:

public static Dictionary<TKey, TValue> PToDictionary<TKey, TValue, TKeyProto, TValueProto>(
    MapField<TKeyProto, TValueProto> keyValuePairs,
    Func<TKeyProto, TKey> mapKey,
    Func<TValueProto, TValue> mapValue
)
{
    // this is possible because MapField<TKey, TValue> implements IEnumerable<KeyValuePair<TKey, TValue>>
    return keyValuePairs.ToDictionary(
        (KeyValuePair<TKeyProto, TValueProto> kvp) => mapKey(kvp.Key),
        (KeyValuePair<TKeyProto, TValueProto> kvp) => mapValue(kvp.Value));
}

For example, if you want to convert MapField<string, string> to Dictionary<Uri, int> you can use the following code:

Dictionary<Uri, int> dictionary = PToDictionary(
    map,
    key => new Uri(key),
    val => int.Parse(val));

CodePudding user response:

Just replace your types with generic type parameters:

private static Dictionary<T1, T2> PToDictionary<T1, T2>(MapField<T1, T2> keyValuePairs)
{
    Dictionary<T1, T2> keyValues = new();
    foreach (var pair in keyValuePairs)
    {
       keyValues[pair.Key] = pToR(pair.Value);
    }
    return keyValues;
}

Note that PToDictionary<TKey, TValue>(MapField<TKeyProto,TValueProto> m1, Func<Tkey>(TKeyProto) keyFunc, Func<TValue>(TValueProto) valueFunc) is just incorrect.

First of all Func<Tkey>(TKeyProto)is not correct syntax, it should be Func<TKeyProto, Tkey> to declare a function taking a TKeyProto, and returning a TKey. You also need to declare all generic type parameters, i.e. PToDictionary<TKey, TValue, TKeyProto, TValueProto>. Buy you might as well just use the existing .ToDictionary extension method

  • Related