Home > Enterprise >  LINQ - Dynamically Invoke ToDictionary
LINQ - Dynamically Invoke ToDictionary

Time:06-21

Is there a way in .Net to dynamically invoke ToDictionary(<lambda key>, <lambda val>) to reduce boilerplate of returning a Dictionary when running LINQ expressions.

C# Example:

Dictionary<string, object> d_filt;

Dictionary<string, object> d_in = new Dictionary<string, object>();
d_in.Add("k1", 4);
d_in.Add("k2", 3);
d_in.Add("k3", 2);
d_in.Add("k4", 1);

// Current Expression:
d_filt = d_in.Where(p => p.value > 2)
             .ToDictionary(p => p.Key, p => p.Value);

// Preferred Expression:
d_filt = linq2Dict(d_in.Where(p => p.value > 2));

Where linq2Dict(<LinqObj>) is a helper that will dynamically invoke the ToDictionary(..) method.

I have tried Reflection library but it appears that ToDictionary is not available through the standard Reflection library I'm familiar with.

Note: VB is even more verbose:

Dim d_filt = d_in.Where(Function(p) p.value > 2).ToDictionary(Function(p) p.Key, Function(p) p.Value)

Of course, the slickest solution would be to add a ToDict() Extension which took no arguments resulting in:

// Preferred Expression:
d_filt = d_in.Where(p => p.value > 2).ToDict()

CodePudding user response:

No reflection is necessary, just plain ol' generic

public static class Convert
{
    public static Dictionary<T,U> ToDict<T,U>(this IEnumerable<KeyValuePair<T,U>> source) where T : notnull
    {
        return source.ToDictionary(s=>s.Key,s=>s.Value);
    }
}

The constraint for T is because Dictionary can't use null keys.

As a bonus it maintains the fluent syntax, so you can just use

d_filt = d_in.Where(p => p.value > 2).ToDict();

CodePudding user response:

To build on @Martheen's answer, here is how to implement ToDict() extension in VB:

Imports System.Runtime.CompilerServices

Module Convert
    <Extension()>
    Function ToDict(Of T, U)(ByVal source As IEnumerable(Of KeyValuePair(Of T, U))) As Dictionary(Of T, U)
        Return source.ToDictionary(Function(s) s.Key, Function(s) s.Value)
    End Function
End Module

CodePudding user response:

Here is an implementation of linq2Dict() in VB:

Public Shared Function linq2Dict(Of T, U)(ByVal source As IEnumerable(Of KeyValuePair(Of T, U))) As Dictionary(Of T, U)
    Return source.ToDictionary(Function(s) s.Key, Function(s) s.Value)
End Function

Eg:

d_filt = linq2Dict(d_in.Where(p => p.value > 2))
  • Related