开发者

Empty ILookup<K, T>

I have a method that returns a开发者_StackOverflow中文版n 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?


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; }
    }
}


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.


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<,>) {
 // ....
}


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>()


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!


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));
}


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);
    }

}


You can return null

or Exception

But you should note it in class comment

Added:+ This is more obvious than some extension method

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜