Frans Bouma's blog

Generator.CreateCoolTool();

Syndication

News



    Visit LLBLGen Pro's website

    Follow me on Twitter

    Add to Technorati Favorites

About me

Fun stuff I created

My work

Multi-value Dictionary C# source code (.NET 3.5)

By popular demand, I've published the C# source code of my Multi-value Dictionary class, which can also merge dictionaries into itself and which implements ILookup<T, V> as well. It's part of Algorithmia, our upcoming data-structure and algorithm library which will ship with LLBLGen Pro v3.0 later this year. The code is released under the BSD2 license, see the enclosed readme.txt. The class comes with its own general purpose Grouping<T, V> class as well and of course its own ToMultiValueDictionary() extension method.

I hope this is useful to others.

Update: it seems that if you run a Linq query (Linq to objects) over the MultiValueDictionary, the compiler and intellisense get confused as there are now two enumerators and both work with the linq operators, which means you either want to remove the ILookup code from the class (which is not that hard) or explicitly state the generic arguments. It's not a big problem, though in case you run into this problem, you know the reason.

Update 2:A user pointed out that I forgot to include ArgumentVerifier, a simple class to make life easier wrt verifying arguments, so I've included that one as well.

Published Monday, May 18, 2009 10:52 AM by FransBouma

Comments

# re: Multi-value Dictionary C# source code (.NET 3.5)@ Monday, May 18, 2009 3:21 PM

>> the compiler and intellisense get confused

Perhaps you need to rethink the design? :-)

Steven

# re: Multi-value Dictionary C# source code (.NET 3.5)@ Monday, May 18, 2009 3:45 PM

@Steven: I have no choice: the class inherits from Dictionary (implements IEnumerable<>) and ILookup also implements IEnumerable<> but different generic types. So ILookup has to change, but that's not my call (it's a BCL interface ;)).

FransBouma

# re: Multi-value Dictionary C# source code (.NET 3.5)@ Wednesday, May 20, 2009 4:38 AM

nice

belayet hossain

# re: Multi-value Dictionary C# source code (.NET 3.5)@ Wednesday, May 20, 2009 5:27 AM

You can make the ILookup<> implementation explicit. That way, if anyone wants the ILookup<> functions, they can cast to ILookup<> (and thus get the appropriate extension methods).

Otherwise, the default behavior would be that intellisense will show only fields (and extensions) from non-explicitly implemented interfaces.

Mark Smeltzer

# re: Multi-value Dictionary C# source code (.NET 3.5)@ Wednesday, May 20, 2009 5:50 AM

@Mark: I made it explicit, that's the point: a Linq to objects enumerable method like Where also works with ILookup<T, U>.IEnumerable<IGrouping<T, U>>, which makes it problematic because there are now two enumerables and which one to choose by the compiler? so the compiler wants to explicitly define the generic parameters on the linq extension methods, which is awkward.

FransBouma

# re: Multi-value Dictionary C# source code (.NET 3.5)@ Wednesday, May 20, 2009 6:22 AM

Wow. You're right. I just brewed up a test class that implements IEnumerable<string> and explicitly implements ILookup<string,string>.

While intellisense correctly shows the overloads for the extension methods of associated with the IEnumerable<string> interface, it appears that the parser/compiler gets confused about how to interpret the various extension methods that are applicable to the explicitly defined ILookup<string, string> interface.

I had (incorrectly) assumed that Microsoft made the parser/compiler mirror the functionality of the intellisense drop down. That seems like a design flaw to me...

So, yeah, I guess the only thing left is something like this: add a property called "Values" (or whatever seems appropriate) that returns an IEnumerable<T>, which iterates over the same enumeration that the IEnumerable<T> implementation that the dictionary's IEnumerable<T> implementation iterates over. That could be implemented as a simple redirection, but it would make both the compiler and intellisense happy.

That way the user can do something like this:

  var dictionary = GetMultiValueDictionary();

  dictionary.Values.Select( t=> t.Length ).Where( t=> t > 0 );

This could even be implemented externally as an extension method instead of as a property on the original class:

  var dictionary = GetMultiValueDictionary();

  dictionary.GetValues().Select( t=> t.Length ).Where( t=> t > 0 );

Mark Smeltzer

# re: Multi-value Dictionary C# source code (.NET 3.5)@ Wednesday, May 20, 2009 11:25 AM

@Mark: I think the compiler simply checks whether a type implements IEnumerable<T> and as the type implements that interface twice (once as the Dictionary<> and once as ILookup<>), it gets confused. As ILookup seems to be some kind of specific linq query interface, I think the scope for the interface is smaller than the one it is used in with this class.

the GetValues is indeed a 'workaround', though thinking about ILookup some more, I think it shouldn't be on this dictionary, it doesn't really add anything.

FransBouma

# re: Multi-value Dictionary C# source code (.NET 3.5)@ Tuesday, May 26, 2009 8:34 AM

a newbie and stupid question, but why do I need it?

e.g. As I understand it is for storing values with 2 different keys.

How would I connect it to a relational world, e.g. what to store in such a collection? Sometimes your articles are hard to read for not-godlike coders like you ;p

Steve Raynolds

# re: Multi-value Dictionary C# source code (.NET 3.5)@ Tuesday, May 26, 2009 9:12 AM

@Steve: in the relational world, it can be very handy :) How about you have a list of Order objects, and you want to store all orders under their customerid FK field value? With this dictionary you can do that: the customerid field is the key, the values are the order instances, which allows you to quickly find the Order instances for a given customerID in memory using the dictionary without needing to traverse all orders sequentially

FransBouma