I have a method that returns an ILookup
. In some cases I want to return an empty ILookup
as an early exit. What is the best way of constructing an empty ILookup
?
-
What types are you using as K and T in your ILookup
? – Chaim Zonnenberg Jul 25 '11 at 19:53
8 Answers
Further to the answers from mquander and Vasile Bujac, you could create a nice, straightforward singleton-esque EmptyLookup<K,E>
class as follows. (In my opinion, there doesn't seem much benefit to creating a full ILookup<K,E>
implementation as per Vasile's answer.)
var empty = EmptyLookup<int, string>.Instance;
// ...
public static class EmptyLookup<TKey, TElement>
{
private static readonly ILookup<TKey, TElement> _instance
= Enumerable.Empty<TElement>().ToLookup(x => default(TKey));
public static ILookup<TKey, TElement> Instance
{
get { return _instance; }
}
}
-
Thanks to mquander and Vasile but I think this merge of the two solutions is the simplest/best. – Mike Q Jul 26 '11 at 07:21
There's no built-in, so I'd just write an extension method that runs something along the lines of new T[0].ToLookup<K, T>(x => default(K));
I strongly doubt returning null would be more correct here. It's almost never the case that you want to return null from a method which returns a collection (as opposed to an empty collection.) I could not possibly disagree more with people who are suggesting that.

- 70,359
- 14
- 95
- 123
-
The semantics of the return value need to be considered. For example, a search that returns no results should return an empty collection, but a search that has (for example) failed or had invalid parameters should return `null`. – Adam Maras Jul 25 '11 at 19:55
-
3Well, a search that has invalid parameters (as in, invalid arguments to a method, I presume) should probably throw. But I take your meaning. It's certainly common that a method will return an empty collection, though, and it would usually be a mess to return null in that case. – mqp Jul 25 '11 at 19:57
-
You are indeed correct regarding throwing upon error. However, I've worked with business applications where, for example, certain external systems would become unavailable during certain times of day; in such cases, queries and requests would fail, but it's not an "exceptional" case, as it was expected behavior. – Adam Maras Jul 25 '11 at 19:58
-
@mquander - Totally agree about null. Empty something is almost always the better option. – Mike Q Jul 26 '11 at 07:19
-
I agree about throwing instead of returning null - throw a useful exception (don't strip information!) and save yourself a future runtime debugging headache. – jocull Nov 01 '17 at 22:03
You can create a singleton class for empty lookups.
using System.Linq;
public sealed class EmptyLookup<T, K> : ILookup<T, K>
{
public static readonly EmptyLookup<T, K> Instance { get; }
= new EmptyLookup<T, K>();
private EmptyLookup() { }
public bool Contains(T key) => false;
public int Count => 0;
public IEnumerable<K> this[T key] => Enumerable.Empty<K>();
public IEnumerator<IGrouping<T, K>> GetEnumerator()
=> Enumerable.Empty<IGrouping<K, V>>().GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
}
then you can write code like this:
var x = EmptyLookup<int, int>.Instance;
The benefit of creating a new class is that you can use the "is" operator and check for type equality:
if (x is EmptyLookup<,>) {
// ....
}

- 5,043
- 2
- 26
- 30
-
-
Thanks, looks good. I would suggest that [] should throw KeyNotFoundException rather than NotImplementedException. – Mike Q Jul 26 '11 at 07:18
-
3Actually the .NET implementation of `Lookup
` returns an empty sequence if _key_ is not found in the collection – Vasea Mar 28 '13 at 08:35 -
All good, except the suggestion of the equality check. You shouldn't rely on the lookup being an instance of EmptyLookup to check if it's empty. – Michael Fry Aug 09 '23 at 04:41
Based on LukeH answer, I'd create a static class Lookup
with an Empty<TKey, TElement>
method. In this way you could use is just the same way as Enumerable.Empty<T>
.
public static class Lookup
{
public static ILookup<TKey, TElement> Empty<TKey, TElement>()
=> Enumerable.Empty<TElement>().ToLookup(x => default(TKey));
}
Example Usage: Lookup.Empty<string, string>()

- 126
- 1
- 6
-
2I like this API. But I think it would be better to cache the result of this method in the same way `Enumerable.Empty
` does. As shown in https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,4d026772cf3399f5 it is calling to a static property in an internal class. – Mariano Desanze Mar 29 '19 at 22:21
Create an empty list, then execute ToLookup() on it, like this:
List<Point> items = new List<Point>();
ILookup<int, int> lookup = items.ToLookup(p => p.X, p => p.Y);
Good luck!

- 2,607
- 1
- 16
- 22
Thanks @mqp for the good idea. I can propose several extension methods based on that approach:
public static class IEnumerableExtensions
{
public static ILookup<TKey, TElement> ToEmptyLookup<TKey, TElement>(this IEnumerable<TElement> elements) => new TElement[0].ToLookup(k => default(TKey));
public static ILookup<TKey, TElement> ToEmptyLookup<TKey, TElement>(this IDictionary<TKey, TElement> elements) => new TElement[0].ToLookup(k => default(TKey));
public static ILookup<TKey, TElement> ToEmptyLookup<TKey, TElement>(this IGrouping<TKey, TElement> elements) => new TElement[0].ToLookup(k => default(TKey));
public static ILookup<TKey, TElement> ToEmptyLookup<TKey, TElement>(this IEnumerable<ILookup<TKey, TElement>> elements) => new TElement[0].ToLookup(k => default(TKey));
}

- 700
- 11
- 23
Or something more in the spirit of LINQ:
public static class Utility
{
public static ILookup<TKey, TElement> EmptyLookup<TKey, TElement>(Func<TKey, TKey> keySelector,
Func<TKey, TElement> elementSelector)
{
return Enumerable.Empty<TKey>().ToLookup(keySelector, elementSelector);
}
}

- 117
- 1
- 6
You can return null
or Exception
But you should note it in class comment
Added:+ This is more obvious than some extension method

- 1,928
- 2
- 20
- 30
-
5I totally disagree. If a function returns a lookup mapping some `K`s to `T`s, and it so happens that there are no `K`s or `T`s, it's dead obvious that the function should return an empty lookup. It doesn't make any sense to return null or throw an exception, and suddenly have to check for it everywhere, when it would have just worked out of the box if you had returned an empty lookup. – mqp Jul 25 '11 at 20:14
-
"ILookup as an early exit" - This is a typical case when you should throw an exception. – Alexander Molodih Jul 26 '11 at 04:43
-
If you place comment aboute exception, all other developers see it in style sence. And process that exception. – Alexander Molodih Jul 26 '11 at 04:45
-
-
I agree with mquander, if a function returns a collection/map type then "no items" should translate to empty instance rather than null. When I say early exit I mean an initial condition is checked and it find the method has no work to do so I just want to return nothing/empty. – Mike Q Jul 26 '11 at 07:15